Cod sursa(job #2168354)

Utilizator andrei.arnautuAndi Arnautu andrei.arnautu Data 14 martie 2018 10:33:41
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.3 kb
/**
  *  Worg
  *  Mar 14, 2018
  *  9:37:06 AM
  */
#include <cstdio>
#include <vector>
#include <algorithm>

#define mid ((left + right) / 2)
#define leftSon (node * 2)
#define rightSon (node * 2 + 1)

FILE *fin = freopen("heavypath.in", "r", stdin); FILE *fout = freopen("heavypath.out", "w", stdout);

const int maxN = 1e5 + 5;

/*-------- Structures --------*/
struct Node;
struct Chain;

struct Node {
  int idx, value, depth, weight;

  std::vector<Node* > adj;

  Chain *chain;
};

struct Chain {
  Node* father;
  std::vector<Node* > nodes;
  std::vector<int > aint;

  int cnt;
  int maxDepth, delay;
  bool ok;

  Chain() {ok = false; cnt = 0;}
};
/*-------- Data --------*/
int n, m;

Node graph[maxN];
/*-------- --------*/

void ReadGraph() {
  scanf("%d%d", &n, &m);
  for(int i = 1; i <= n; i++) {
    scanf("%d", &graph[i].value); graph[i].idx = i;
  }
  for(int i = 1; i < n; i++) {
    int u, v; scanf("%d%d", &u, &v);

    graph[u].adj.push_back(&graph[v]);
    graph[v].adj.push_back(&graph[u]);
  }
}

void DFS(Node *node, int dad, int depth) {
  node->depth = depth; node->weight = 1;

  Node *son;
  int son_weight = 0;

  for(auto& nxt : node->adj) {
    if(nxt->idx == dad) continue;

    DFS(nxt, node->idx, depth + 1);

    node->weight += nxt->weight;
    if(son_weight < nxt->weight) {
      son = nxt; son_weight = nxt->weight;
    }
  }

  if(son_weight == 0) {  //  Make new chain
    node->chain = new Chain();
  } else {  //  Add node to son's chain
    node->chain = son->chain;

    for(auto& nxt : node->adj) {
      if(nxt->idx == dad || nxt->idx == son->idx) continue;

      nxt->chain->father = node;
    }
  }

  node->chain->nodes.push_back(node);
  node->chain->cnt++;
}

void Update(std::vector<int > &aint, int node, int left, int right, int pos, int value) {
  if(left == right) {
    aint[node] = value; return;
  } else {
    if(pos <= mid) {
      Update(aint, leftSon, left, mid, pos, value);
    } else {
      Update(aint, rightSon, mid + 1, right, pos, value);
    }

    aint[node] = std::max(aint[leftSon], aint[rightSon]);
  }
}

void Decompose() {
  DFS(&graph[1], 0, 1);
  graph[0].depth = 0; graph[1].chain->father = &graph[0];

  //  Build aints
  for(int i = 1; i <= n; i++) {
    if(graph[i].chain->ok == true) continue;

    Chain *chain = graph[i].chain;

    int space = (int)chain->nodes.size() + 1;
    chain->aint = std::vector<int >(space * 4, 0);

    chain->maxDepth = chain->nodes[0]->depth;
    chain->delay = chain->nodes.back()->depth - 1;

    for(auto& node : chain->nodes) {
      Update(chain->aint, 1, 1, chain->cnt, node->depth - chain->delay, node->value);
    }

    chain->ok = true;
  }
}

void QueryAint(std::vector<int > &aint, int node, int left, int right, int first, int last, int &ans) {
  if(first <= left && right <= last) {
    ans = std::max(ans, aint[node]); return;
  }

  if(first <= mid) {
    QueryAint(aint, leftSon, left, mid, first, last, ans);
  }
  if(mid < last) {
    QueryAint(aint, rightSon, mid + 1, right, first, last, ans);
  }
}

int Query(Node *u, Node *v) {
  int ans = 0;

  if(u->chain == v->chain) {
    int hmin = std::min(u->depth, v->depth), hmax = std::max(u->depth, v->depth);
    Chain *chain = u->chain;

    QueryAint(chain->aint, 1, 1, chain->cnt, hmin - chain->delay, hmax - chain->delay, ans);
  } else {
    if(u->chain->father->depth > v->chain->father->depth) {
      Chain *chain = u->chain;

      QueryAint(chain->aint, 1, 1, chain->cnt, 1, u->depth - chain->delay, ans);

      ans = std::max(ans, Query(chain->father, v));
    } else {
      Chain *chain = v->chain;

      QueryAint(chain->aint, 1, 1, chain->cnt, 1, v->depth - chain->delay, ans);

      ans = std::max(ans, Query(u, chain->father));
    }
  }

  return ans;
}

void ProcessQueries() {
  for(int i = 0; i < m; i++) {
    int type, x, y; scanf("%d%d%d", &type, &x, &y);

    if(type == 0) {
      graph[x].value = y;

      Chain *chain = graph[x].chain;
      Update(chain->aint, 1, 1, chain->cnt, graph[x].depth - chain->delay, graph[x].value);
    } else {
      printf("%d\n", Query(&graph[x], &graph[y]));
    }
  }
}

int main() {
  ReadGraph();

  Decompose();

  ProcessQueries();

  return 0;
}