Cod sursa(job #2706286)

Utilizator vladm98Munteanu Vlad vladm98 Data 14 februarie 2021 15:19:59
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.37 kb
#include <bits/stdc++.h>
using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
const int N = 100001;

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