Cod sursa(job #2706547)

Utilizator Katherine456719Swan Katherine Katherine456719 Data 15 februarie 2021 11:49:01
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.42 kb
#include <bits/stdc++.h>
using namespace std;
const int N = 100001;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

int nodevalue[N],poz[N],level[N],where[N],father[N],weight[N];
vector <int> graph[N];
vector <int> hp[N];
vector <int> arbint[N];
int nrhp;

void arint(int nod, int st, int dr, int pos){
    if(st == dr)
    {
        arbint[pos][nod] = nodevalue[hp[pos][st]];
        return;
    }
    int mijl = (st+dr)>>1;
    arint(nod << 1, st, mijl, pos);
    arint(nod << 1 | 1, mijl + 1, dr, pos);
    arbint[pos][nod] = max(arbint[pos][nod << 1],arbint[pos][nod << 1 | 1]);
}

void update(int node, int st,int dr, int poz, int val, int currentaint){
    if(st == dr)
    {
        arbint[currentaint][node] = val;
        return;
    }
    int mij = (st+dr)>>1;
    if(poz <= mij)
        update(node << 1, st, mij, poz, val,currentaint);
    else
        update(node << 1 | 1, mij + 1, dr, poz, val, currentaint);
    arbint[currentaint][node] = max(arbint[currentaint][node << 1], arbint[currentaint][node << 1 | 1]);
}

void hpd(int node, int father1){
    father[node] = father1;
    level[node] = level[father1]+1;
    weight[node] = 1;
    for(auto x : graph[node])
    {
        if(x != father1){
            hpd(x, node);
            weight[node] += weight[x];
        }
    }
    if(weight[node] == 1) {
        ++nrhp;
        where[node] = nrhp;
        poz[node] = 0;
        hp[nrhp].push_back(node);
        return;
    }
    int good = 0;
    for(auto x : graph[node])
    {
        if(x==father1)continue;
        if(weight[x] > weight[good])
            good = x;
    }
    where[node] = where[good];
    poz[node] = (int)hp[where[node]].size();
    hp[where[node]].push_back(node);
}

int query(int node, int st, int dr, int a, int b, int currentaint){
     if(a <= st && b >= dr)
         return arbint[currentaint][node];
     int mij = (st + dr) >> 1;
     int maxs = -1,maxd = -1;
     if(a <= mij) maxs = query(node << 1, st, mij, a, b, currentaint);
     if(b > mij) maxd = query(node << 1 | 1, mij + 1, dr, a, b, currentaint);
     return max(maxs,maxd);
}

int solve(int x, int y){
      int ans = -1;
      int lantx = where[x], lanty = where[y];
      if(lantx == lanty)
      {
          int a = min(poz[x],poz[y]), b = max(poz[x], poz[y]);
          ans = max(ans, query(1, 0, hp[lantx].size() - 1, a, b, lantx));
      }
      else
      {
          if(level[hp[lantx][0]] < level[hp[lanty][0]])
          {
             swap(x, y);
             swap(lantx, lanty);
          }
          ans = max(ans, query(1, 0, hp[lantx].size() - 1, 0, poz[x], lantx));
          ans = max(ans, solve(father[hp[lantx][0]],y));
      }
      return ans;
}

int main() {
    int n,m;
    fin >> n >> m;
    for(int i = 1;i <= n; ++i)
        fin >> nodevalue[i];
    for(int i = 1; i< n; ++i)
    {
        int x, y;
        fin >> x >> y;
        graph[x].push_back(y);
        graph[y].push_back(x);
    }
    hpd(1,0);

    for (int i = 1; i <= nrhp; ++i)
        reverse(hp[i].begin(), hp[i].end());
    for (int i = 1; i<=n; ++i)
        poz[i] = (int)hp[where[i]].size() - 1 - poz[i];
    for (int i = 1; i<= nrhp; ++i){
        arbint[i].resize(hp[i].size() << 2);
        arint(1, 0, (int)hp[i].size() - 1, i);
    }
    for(int i = 1;i <= m; ++i)
    {
        int t, x, y;
        fin >> t >> x >> y;
        if(t == 1)
            fout<< solve(x,y) << "\n";
        else update(1, 0, hp[where[x]].size() - 1, poz[x], y ,where[x]);
    }
    return 0;
}