Cod sursa(job #2271319)

Utilizator MoodyFaresFares Mohamad MoodyFares Data 28 octombrie 2018 13:29:01
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.17 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 head;
  int dad;
  int dadDepth;
  
  Chain() {
    head = 1;
    dad = 0;
    dadDepth = 0;
  }
};

int n;
int a[1 + MAX_N];
std::vector<int> g[1 + MAX_N];
bool viz[1 + MAX_N];
int treeSize[1 + MAX_N];
std::vector<int> heavyPath;
int heavySon[1 + MAX_N];
int posHeavyPath[1 + MAX_N];
int chainCount = 1;
int chainId[1 + MAX_N];
Chain chain[1 + MAX_N];
int arbint[1 + 4 * MAX_N];
//SegmentTree* root = new SegmentTree;

void update(int nod, int poz, int val, int st, int dr) {
  if(st == dr) {
    arbint[nod] = val;
    return ;
  }
  int mij = (st + dr) / 2;
  if(poz <= mij)
    update(nod * 2, poz, val, st, mij);
  else
    update(nod * 2 + 1, poz, val, mij + 1, dr);
  arbint[nod] = std::max(arbint[nod * 2], arbint[nod * 2 + 1]);
}

int query(int nod, int a, int b, int st, int dr) {
  if(a <= st && dr <= b)
    return arbint[nod];
  int sol1 = 0, sol2 = 0;
  int mij = (st + dr) / 2;
  if(a <= mij)
    sol1 = query(nod * 2, a, b, st, mij);
  if(mij < b)
    sol2 = query(nod * 2 + 1, a, b, mij + 1, dr);
  return std::max(sol1, sol2);
}

void dfsSize(int v) {
  viz[v] = true;
  treeSize[v] = 1;
  for (auto u : g[v]) {
    if (!viz[u]) {
      dfsSize(u);
      treeSize[v] += treeSize[u];
      if (treeSize[heavySon[v]] < treeSize[u])
        heavySon[v] = u;
    }
  }
}

void dfsHeavy(int v, int depth) {
  if (v == 7) {
    v++;
    v--;
  }
  viz[v] = true;
  heavyPath.push_back(v);
  posHeavyPath[v] = (int)heavyPath.size();
  chainId[v] = chainCount;
  if (heavySon[v] != 0) {
    dfsHeavy(heavySon[v], depth + 1);
    for (auto u : g[v]) {
      if (!viz[u] && u != heavySon[v]) {
        chainCount++;
        chain[chainCount].head = u;
        chain[chainCount].dad = v;
        chain[chainCount].dadDepth= depth;
        dfsHeavy(u, depth + 1);
      }
    }
  }
}


int pathMax(int u, int v) {
  if (chainId[u] == chainId[v])
    return query(1, std::min(posHeavyPath[u], posHeavyPath[v]), std::max(posHeavyPath[u], posHeavyPath[v]), 1, n);
  else {
    if (chain[chainId[u]].dadDepth < chain[chainId[v]].dadDepth)
      std::swap(u, v);
    int tempAns = query(1, posHeavyPath[chain[chainId[u]].head], posHeavyPath[u], 1, n);
    return std::max(tempAns, pathMax(chain[chainId[u]].dad, v));
  }
}

int main() {
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  
  int 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);
  for (int i = 1; i <= n; i++)
    viz[i] = false;
  dfsHeavy(1, 1);
  //root->build(1, n);
  int pos = 0;
  for (auto it : heavyPath)
    update(1, ++pos, a[it], 1, n);
    //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)
      update(1, posHeavyPath[x], y, 1, n);
      //root->update(posHeavyPath[x], y);
    else
      printf("%d\n", pathMax(x, y));
  }
  return 0;
}