Cod sursa(job #1569410)

Utilizator usermeBogdan Cretu userme Data 15 ianuarie 2016 15:20:07
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.69 kb
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <algorithm>

using std::vector;
using std::queue;
using std::swap;
using std::max;

const int MAX_N = 100000;

int N, M;

int v[1 + MAX_N];
int father[1 + MAX_N];
vector<int> sons[1 + MAX_N];
vector<int> g[1 + MAX_N];

int maxim[MAX_N];



const int Inf = 1000000000;
int t [1 << 18];
int poz, val, a, b, rez;

void inline query(int p, int st, int dr)
{
    if (a <= st && dr <= b)
    {
        rez = t [p];
        return;
    }

    int m = (st + dr) / 2, m1 = - Inf, m2 = - Inf;

    if (a <= m)
    {
        query (2 * p, st, m);
        m1 = rez;
    }

    if (m + 1 <= b)
    {
        query (2 * p + 1, m + 1, dr);
        m2 = rez;
    }

    rez = max (m1, m2);
}

void inline update (int p, int st, int dr)
{
    if (st == dr)
    {
        t [p] = val;
        return;
    }

    int m = (st + dr) / 2;

    if (poz <= m)
        update (2 * p, st, m);
    else
        update (2 * p + 1, m + 1, dr);

    t [p] = max (t [2 * p], t [2 * p + 1]);
}





struct Node;

struct Chain {
  Node* top;
  int size;
  int offset;

  Chain() {
    this->top = NULL;
    this->size = 0;
    this->offset = 0;
  }

  void setValue(int index, int value) {
    //maxim[this->offset + index] = value;
    poz = this->offset + index;
    val = value;
    update(1, 0, N - 1);
  }

  int getMax(int a, int b) {
    //int i;
    //int answer = 0;
    //for (i = a; i <= b; i++) {
    //  answer = max(answer, maxim[this->offset + i]);
    //}
    //return answer;
    ::a = this->offset + a;
    ::b = this->offset + b;
    rez = 0;
    query(1, 0, N - 1);
    return rez;
  }
};

struct Node {
  int index;
  Node *father;
  int weight;
  int depth;
  int chainPosition;
  Chain *chain;
};

Node nodes[1 + MAX_N];
int chainsCount = 0;
Chain chains[1 + MAX_N];

void dfs2(int node, int nodeFather = 0) {
  for (int neighbour : g[node]) {
    if (neighbour != nodeFather) {
      father[neighbour] = node;
      sons[node].push_back(neighbour);
      dfs2(neighbour, node);
    }
  }
}

void dfs(int node) {
  nodes[node].index = node;
  nodes[node].weight = 1;
  int maxWeightNode = 0;
  for (int son : sons[node]) {
    nodes[son].depth = nodes[node].depth + 1;
    nodes[son].father = &nodes[node];
    dfs(son);
    nodes[node].weight += nodes[son].weight;
    if (nodes[maxWeightNode].weight < nodes[son].weight) {
      maxWeightNode = son;
    }
  }
  if (maxWeightNode != 0) {
    nodes[node].chain = nodes[maxWeightNode].chain;
    nodes[node].chainPosition = nodes[maxWeightNode].chainPosition + 1;
  } else {
    nodes[node].chain = &chains[chainsCount++];
    nodes[node].chainPosition = 0;
  }
  nodes[node].chain->size++;
  nodes[node].chain->top = &nodes[node];
}

void print(int node, int offset = 0) {
  int i;
  for (i = 0; i < offset; i++) {
    printf("  ");
  }
  printf("%d: %d %d %d\n",
      nodes[node].index,
      nodes[node].depth,
      nodes[node].weight,
      nodes[node].chain->top->index);
  for (int son : sons[node]) {
    print(son, offset + 1);
  }
}

int lca(int a, int b) {
  while (nodes[a].chain != nodes[b].chain) {
    if (nodes[a].chain->top->depth < nodes[b].chain->top->depth) {
      swap(a, b);
    }
    a = nodes[a].chain->top->father->index;
  }
  if (nodes[a].depth < nodes[b].depth) {
    return a;
  } else {
    return b;
  }
}

int getMax(int a, int b) {
  int answer = 0;
  while (nodes[a].chain != nodes[b].chain) {
    if (nodes[a].chain->top->depth < nodes[b].chain->top->depth) {
      swap(a, b);
    }
    answer = max(answer, nodes[a].chain->getMax(
        nodes[a].chainPosition, nodes[a].chain->top->chainPosition));
    a = nodes[a].chain->top->father->index;
  }
  if (nodes[b].depth < nodes[a].depth) {
    answer = max(answer, nodes[a].chain->getMax(
        nodes[a].chainPosition, nodes[b].chainPosition));
  } else {
    answer = max(answer, nodes[a].chain->getMax(
        nodes[b].chainPosition, nodes[a].chainPosition));
  }
  return answer;
}

int main() {
  int i;
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  scanf("%d %d", &N, &M);
  for (i = 1; i <= N; i++) {
    scanf("%d", &v[i]);
  }
  for (i = 2; i <= N; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    g[b].push_back(a);
  }
  dfs2(1);
  dfs(1);
  int val = 0;
  for (i = 0; i < chainsCount; i++) {
    chains[i].offset = val;
    val += chains[i].size;
  }
  for (i = 1; i <= N; i++) {
    nodes[i].chain->setValue(nodes[i].chainPosition, v[i]);
  }
  //print(1);

  //*
  for (i = 1; i <= M; i++) {
    int t, x, y;
    scanf("%d %d %d", &t, &x, &y);
    if (t == 0) {
      nodes[x].chain->setValue(nodes[x].chainPosition, y);
    } else { // t == 1
      printf("%d\n", getMax(x, y));
    }
  }//*/
  return 0;
}