Cod sursa(job #2271244)

Utilizator MoodyFaresFares Mohamad MoodyFares Data 28 octombrie 2018 11:58:32
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.39 kb
#include <cstdio>
#include <algorithm>
#include <vector>

const int MAX_N = 100000;

class SegmentTree {
public:
  int value;
  int leftIndex;
  int rightIndex;
  SegmentTree* left;
  SegmentTree* right;
  
  void build(int nodeLeft, int nodeRight) {
    leftIndex = nodeLeft;
    rightIndex = nodeRight;
    int mid = (nodeLeft + nodeRight) >> 1;
    if (leftIndex != rightIndex) {
      left = new SegmentTree;
      left->build(nodeLeft, mid);
      right = new SegmentTree;
      right->build(mid + 1, nodeRight);
    }
  }
  
  void update(int pos, int newValue) {
    if (leftIndex == rightIndex)
      value = newValue;
    else {
      int mid = (leftIndex + rightIndex) >> 1;
      if (pos <= mid)
        left->update(pos, newValue);
      else
        right->update(pos, newValue);
      value = std::max(left->value, right->value);
    }
  }
  
  int query(int qLeft, int qRight) {
    if (qLeft <= leftIndex && rightIndex <= qRight)
      return value;
    else {
      int mid = (leftIndex + rightIndex) >> 1;
      int ans = 0;
      if (qLeft <= mid)
        ans = std::max(ans, left->query(qLeft, qRight));
      if (qRight > mid)
        ans = std::max(ans, right->query(qLeft, qRight));
      return ans;
    }
  }
};

struct Chain {
  int left;
  //int right;
  int dad;
  
  Chain() {
    left = dad = 0;
  }
};

int a[1 + MAX_N];
int treeSize[1 + MAX_N];
int depth[1 + MAX_N];
int heavySon[1 + MAX_N];
std::vector<int> g[1 + MAX_N];
std::vector<int> heavyPath;
int chainId[1 + MAX_N];
int chains;
Chain chain[1 + MAX_N];
int posHeavy[1 + MAX_N];
SegmentTree* root = new SegmentTree;

void dfsSize(int v, int dad) {
  treeSize[v] = 1;
  depth[v] = depth[dad] + 1;
  int biggestSonSize = 0;
  for (auto u : g[v]) {
    if (u != dad) {
      dfsSize(u, v);
      treeSize[v] += treeSize[u];
      if (treeSize[u] > biggestSonSize) {
        biggestSonSize = treeSize[u];
        heavySon[v] = u;
      }
    }
  }
}

void dfsHeavy(int v, int dad) {
  heavyPath.push_back(v);
  posHeavy[v] = (int)heavyPath.size();
  if (heavySon[dad] == v) {
    chainId[v] = chainId[dad];
  }
  else {
    chainId[v] = ++chains;
    chain[chains].left = (int)heavyPath.size();
    chain[chains].dad = dad;
  }
  //chain[chainId[v]].right = (int)heavyPath.size();
  if (heavySon[v] != 0) {
    dfsHeavy(heavySon[v], v);
    for (auto u : g[v]) {
      if (u != dad && u != heavySon[v])
        dfsHeavy(u, v);
    }
  }
}

int pathMax(int u, int v) {
  if (chainId[u] == chainId[v])
    return root->query(std::min(posHeavy[u], posHeavy[v]), std::max(posHeavy[u], posHeavy[v]));
  else {
    if (depth[chain[chainId[u]].dad] < depth[chain[chainId[v]].dad])
      std::swap(u, v);
    int tempAns = root->query(chain[chainId[u]].left, posHeavy[u]);
    return std::max(tempAns, pathMax(chain[chainId[u]].dad, v));
  }
}

int main() {
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++)
    scanf("%d", &a[i]);
  for (int i = 1; i <= n - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    g[v].push_back(u);
    g[u].push_back(v);
  }
  
  dfsSize(1, 0);
  dfsHeavy(1, 0);
  root->build(1, n);
  int pos = 0;
  for (auto it : heavyPath)
    root->update(++pos, a[it]);
  
  for (int i = 1; i <= m; i++) {
    int t, x, y;
    scanf("%d%d%d", &t, &x, &y);
    if (t == 0)
      root->update(posHeavy[x], y);
    else
      printf("%d\n", pathMax(x, y));
  }
  return 0;
}