Cod sursa(job #2447475)

Utilizator andreisontea01Andrei Sontea andreisontea01 Data 13 august 2019 14:25:26
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.22 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 100005;

int val[MAXN], nivel[MAXN], pos[MAXN], lant[MAXN], sub[MAXN], anc[MAXN];
vector<int> graf[MAXN], arb[MAXN], hpd[MAXN];
int lanturi;

void HPDInit(int nod, int tata){
    anc[nod] = tata;
    nivel[nod] = nivel[tata] + 1;
    sub[nod] = 1;
    for(auto x:graf[nod]){
        if(x == tata) continue;
        HPDInit(x, nod);
        sub[nod] += sub[x];
    }
    if(sub[nod] == 1){
        lanturi++;
        hpd[lanturi].push_back(nod);
        lant[nod] = lanturi;
        return;
    }
    int best = 0;
    for(auto x:graf[nod]){
        if(x == tata) continue;
        if(sub[x] > sub[best]) best = x;
    }
    lant[nod] = lant[best];
    hpd[lant[nod]].push_back(nod);
    pos[nod] = (int)hpd[lant[nod]].size() - 1;
}

void ArbInit(int nod, int st, int dr, int lant){
    if(st == dr){
        arb[lant][nod] = val[hpd[lant][st]];
        return;
    }
    int mij = (st + dr) / 2;
    ArbInit(2 * nod, st, mij, lant);
    ArbInit(2 * nod + 1, mij + 1, dr, lant);
    arb[lant][nod] = max(arb[lant][2 * nod], arb[lant][2 * nod + 1]);
}

int query(int nod, int st, int dr, int a, int b, int lant){
    if(a <= st && dr <= b)
        return arb[lant][nod];
    int mij = (st + dr) / 2;
    int maxst = -1, maxdr = -1;
    if(a <= mij) maxst = query(2 * nod, st, mij, a, b, lant);
    if(b > mij) maxdr = query(2 * nod + 1, mij + 1, dr, a, b, lant);
    return max(maxst, maxdr);
}

void update(int nod, int st, int dr, int pozit, int val, int lant){
    if(st == dr && st == pozit){
        arb[lant][nod] = val;
        return;
    }
    int mij = (st + dr) / 2;
    if(pozit <= mij) update(2 * nod, st, mij, pozit, val, lant);
    else update(2 * nod + 1, mij + 1, dr, pozit, val, lant);
    arb[lant][nod] = max(arb[lant][2 * nod], arb[lant][2 * nod + 1]);
}

int findMax(int x, int y){
    int ans = -3;
    if(lant[x] == lant[y]){
        int st = min(pos[x], pos[y]), dr = max(pos[x], pos[y]);
        ans = max(ans, query(1, 0, (int)hpd[lant[x]].size() - 1, st, dr, lant[x]));
    }
    else{
        if(nivel[hpd[lant[x]][0]] < nivel[hpd[lant[y]][0]]) swap(x, y);
        ans = max(ans, query(1, 0, (int)hpd[lant[x]].size() - 1, 0, pos[x], lant[x]));
        ans = max(ans, findMax(anc[hpd[lant[x]][0]], y));
    }
    return ans;
}

int main()
{
    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");
    int n, m;
    fin >> n >> m;
    for(int i = 1; i <= n; ++i)
        fin >> val[i];
    for(int i = 1; i < n; ++i){
        int x, y;
        fin >> x >> y;
        graf[x].push_back(y);
        graf[y].push_back(x);
    }
    HPDInit(1, 0);
    for(int i = 1; i <= lanturi; ++i)
        reverse(hpd[i].begin(), hpd[i].end());
    for(int i = 1; i <= n; ++i)
        pos[i] = (int)hpd[lant[i]].size() - 1 - pos[i];
    for(int i = 1; i <= lanturi; ++i){
        arb[i].resize((int)hpd[i].size() << 2);
        ArbInit(1, 0, (int)hpd[i].size() - 1, i);
    }
    while(m){
        int op, x, y;
        fin >> op >> x >> y;
        if(op) fout << findMax(x, y) << "\n";
        else update(1, 0, hpd[lant[x]].size() - 1, pos[x], y, lant[x]);
        m--;
    }
    return 0;
}