Cod sursa(job #1698237)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 3 mai 2016 23:30:27
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.42 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

const int N_MAX = 100005;

int n, m, chain;
vector<int> graph[N_MAX];
int v[N_MAX], subCnt[N_MAX], h[N_MAX];
int chainIndex[N_MAX], chainStart[N_MAX], chainEnd[N_MAX];
int chainCount[N_MAX], chainParent[N_MAX], chainPos[N_MAX], chainNode[N_MAX];
int tree[4 * N_MAX];

void Dfs(int x, int p) {
   h[x] = 1 + h[p];
   subCnt[x] = 1;

   for(auto y : graph[x]) {
      if(y != p) {
         Dfs(y, x);
         subCnt[x] += subCnt[y];
      }
   }

   int best = -1;
   for(auto y : graph[x]) {
      if(y != p) {
         if(best == -1 || (best != -1 && subCnt[y] > subCnt[best]))
            best = y;
      }
   }

   for(auto y : graph[x]) {
      if(y != p && y != best) {
         chainParent[chainIndex[y]] = x;
      }
   }

   if(best == -1)
      chainIndex[x] = ++chain;
   else
      chainIndex[x] = chainIndex[best];

   chainCount[chainIndex[x]]++;
}

void DetermineChains() {
   Dfs(1, 0);

   for(int i = 1; i <= chain; i++) {
      chainStart[i] = 1 + chainEnd[i - 1];
      chainEnd[i] = chainStart[i] + chainCount[i] - 1;
   }

   for(int i = 1; i <= n; i++) {
      chainPos[i] = h[i] - h[chainParent[chainIndex[i]]];
      chainNode[chainStart[chainIndex[i]] + chainPos[i] - 1] = i;
   }
}

void Build(int x = 1, int l = 1, int r = n) {
   if(l > r) return;
   if(l == r) {
      tree[x] = v[chainNode[l]];
      return;
   }
   int med = (l + r) >> 1;
   Build(x << 1, l, med);
   Build(x << 1 | 1, med + 1, r);
   tree[x] = max(tree[x << 1], tree[x << 1 | 1]);
}

void Update(int pos, int val, int x = 1, int l = 1, int r = n) {
   if(r < pos || pos < l) return;
   if(l == r) {
      tree[x] = val;
      return;
   }
   int med = (l + r) >> 1;
   Update(pos, val, x << 1, l, med);
   Update(pos, val, x << 1 | 1, med + 1, r);
   tree[x] = max(tree[x << 1], tree[x << 1 | 1]);
}

int Query(int ql, int qr, int x = 1, int l = 1, int r = n) {
   if(r < ql || qr < l) return 0;
   if(ql <= l && r <= qr) return tree[x];
   int med = (l + r) >> 1;
   return max(Query(ql, qr, x << 1, l, med), Query(ql, qr, x << 1 | 1, med + 1, r));
}

int HeavyQuery(int x, int y) {
   int ret = 0;

   while(chainIndex[x] != chainIndex[y]) {
      int xPar = chainParent[chainIndex[x]];
      int yPar = chainParent[chainIndex[y]];

      if(h[xPar] > h[yPar]) {
         ret = max(ret, Query(chainStart[chainIndex[x]], chainStart[chainIndex[x]] + chainPos[x] - 1));
         x = xPar;
      }
      else {
         ret = max(ret, Query(chainStart[chainIndex[y]], chainStart[chainIndex[y]] + chainPos[y] - 1));
         y = yPar;
      }
   }

   return max(ret, Query(chainStart[chainIndex[x]] + min(chainPos[x], chainPos[y]) - 1,
                         chainStart[chainIndex[x]] + max(chainPos[x], chainPos[y]) - 1));
}

int main() {
   ifstream f("heavypath.in");
   ofstream g("heavypath.out");

   f >> n >> m;

   for(int i = 1; i <= n; i++)
      f >> v[i];

   for(int i = 1; i < n; i++) {
      int x, y;

      f >> x >> y;
      graph[x].push_back(y);
      graph[y].push_back(x);
   }

   DetermineChains();
   Build();

   while(m--) {
      int t, x, y;

      f >> t >> x >> y;
      if(t == 0)
         Update(chainStart[chainIndex[x]] + chainPos[x] - 1, y);
      else
         g << HeavyQuery(x, y) << '\n';
   }

   return 0;
}