Cod sursa(job #1698246)

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

using namespace std;

const int N_MAX = 100005;

int n, m, chains;
vector<int> graph[N_MAX], chain[N_MAX];
int v[N_MAX], siz[N_MAX], h[N_MAX];
int indx[N_MAX], upLink[N_MAX], pos[N_MAX], node[N_MAX], tree[4 * N_MAX];

void Dfs(int x, int p) {
   int best = -1;

   h[x] = 1 + h[p];
   siz[x] = 1;

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

         if(best == -1 || siz[best] < siz[y])
            best = y;
      }
   }

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

   indx[x] = (best == -1 ? ++chains : indx[best]);
   chain[indx[x]].push_back(x);
}

void Build(int x = 1, int l = 1, int r = n) {
   if(l > r) return;
   if(l == r) {
      tree[x] = v[node[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(indx[x] != indx[y]) {
      if(h[upLink[indx[x]]] > h[upLink[indx[y]]]) {
         ret = max(ret, Query(pos[x], pos[chain[indx[x]].back()]));
         x = upLink[indx[x]];
      }
      else {
         ret = max(ret, Query(pos[y], pos[chain[indx[y]].back()]));
         y = upLink[indx[y]];
      }
   }
   if(pos[x] > pos[y]) swap(x, y);
   return max(ret, Query(pos[x], pos[y]));
}

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

   for(int i = 1, j = 0; i <= chains; i++) {
      for(auto x : chain[i]) {
         pos[x] = ++j;
         node[j] = x;
      }
   }

   Build();
}

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);
   }

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

      f >> t >> x >> y;
      if(t == 0)
         Update(pos[x], y);
      else
         g << HeavyQuery(x, y) << '\n';
   }

   return 0;
}