Cod sursa(job #3259783)

Utilizator andreic06Andrei Calota andreic06 Data 27 noiembrie 2024 20:00:01
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.47 kb
#include <bits/stdc++.h>

using namespace std;
ifstream in ("heavypath.in");
ofstream out ("heavypath.out");

using int64 = long long;

const int N_MAX = 1e5;
const int Q_MAX = 1e5;

struct defNode {
    int value;
    int siz, depth, p;
    int heavyChild, pos, head; /// poz = pozitia in HLD
} infos[1 + N_MAX];

int N, Q;
vector<int> tree[1 + N_MAX];
void readInput (void) {
   in >> N >> Q;
   for (int node = 1; node <= N; node ++) in >> infos[node].value;
   for (int i = 1; i < N; i ++) {
      int a, b; in >> a >> b;
      tree[a].push_back (b);
      tree[b].push_back (a);
   }
}


void init_dfs (int root, int p) {
    infos[root].siz = 1;
    infos[root].depth = infos[p].depth + 1;
    infos[root].p = p;
    for (int node : tree[root]) {
       if (node == p) continue;
       init_dfs (node, root);
       infos[root].siz += infos[node].siz;
    }
}

void dfs_HLD (int root, int p, int currHead) {
   infos[root].head = currHead;

   int t = 0;
   for (int node : tree[root]) {
      if (node == p) continue;
      if (infos[node].siz > infos[t].siz) t = node;
   }
   infos[root].heavyChild = t;
   for (int node : tree[root]) {
      if (node != p && node != infos[root].heavyChild)
        dfs_HLD (node, root, node);
   }
   if (infos[root].heavyChild) dfs_HLD (infos[root].heavyChild, root, currHead);
}


int order[1 + N_MAX];
void construct_HLD (void) {
    int pos = 0;
    for (int node = 1; node <= N; node ++) {
       if (infos[node].head == node) {
         int aux = node;
         while (aux) {
            ///cout << aux << " ";
            order[++ pos] = aux;
            infos[aux].pos = pos;
            aux = infos[aux].heavyChild;
         }
         ///cout << "\n";
       }
    }
}



int ST[1 + 4 * N_MAX];
void update (int node, int left, int right, int pos, int newValue) {
    if (left == right)
      ST[node] = newValue;
    else {
      int mid = left + (right - left) / 2;
      if (pos <= mid) update (2 * node, left, mid, pos, newValue);
      else update (2 * node + 1, mid + 1, right, pos, newValue);
      ST[node] = max (ST[2 * node], ST[2 * node + 1]);
    }
}
int query (int node, int left, int right, int qleft, int qright) {
   if (qleft <= left && right <= qright) return ST[node];
   int mid = left + (right - left) / 2;

   int ret = 0;
   if (qleft <= mid) ret = max (ret, query (2 * node, left, mid, qleft, qright));
   if (mid + 1 <= qright) ret = max (ret, query (2 * node + 1, mid + 1, right, qleft, qright));
   return ret;
}

int query_HLD (int a, int b) {
   int answer = 0;
   while (infos[a].head != infos[b].head) {
      if (infos[infos[a].head].depth < infos[infos[b].head].depth) swap (a, b);
      int start = infos[infos[a].head].pos;
      answer = max (answer, query (1, 1, N, start, infos[a].pos));
      a = infos[infos[a].head].p;
   }
   if (infos[a].pos > infos[b].pos) swap (a, b);
   answer = max (answer, query (1, 1, N, infos[a].pos, infos[b].pos));
   return answer;
}


int main()
{
   readInput ();
   init_dfs (1, 0);
   dfs_HLD (1, 0, 1);
   construct_HLD ();
   for (int i = 1; i <= N; i ++) update (1, 1, N, i, infos[order[i]].value);

   for (int i = 1; i <= Q; i ++) {
      int t; in >> t;
      if (t == 0) {
        int node, x; in >> node >> x;
        update (1, 1, N, infos[node].pos, x);
      }
      else {
        int a, b; in >> a >> b;
        out << query_HLD (a, b) << "\n";
      }
   }

    return 0;
}