Cod sursa(job #2399265)

Utilizator andreisontea01Andrei Sontea andreisontea01 Data 7 aprilie 2019 11:12:57
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;

const int MAXN = 100005;

int lanturi;
vector <int> graf[MAXN];
vector <int> arb[MAXN];
vector <int> hpd[MAXN];
int nivel[MAXN];
int lant[MAXN];
int sub[MAXN];
int tata[MAXN];
int poz[MAXN];
int val[MAXN];

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

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

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

void Update(int node, int st, int dr, int pozit, int val, int aint){
    if (st == dr){
        arb[aint][node] = val;
        return ;
    }
    int mij = (st + dr) / 2;
    if (pozit <= mij)
        Update(node * 2, st, mij, pozit, val, aint);
    else
        Update(node * 2 + 1, mij + 1, dr, pozit, val, aint);
    arb[aint][node] = max(arb[aint][node * 2], arb[aint][node * 2 + 1]);

}

int findMaxim(int x, int y){
    int ans = -3;
    int lx = lant[x], ly = lant[y];
    if (lx == ly){
        int a = min(poz[x], poz[y]), b = max(poz[x], poz[y]);
        ans = max(ans, Query(1, 0, int(hpd[lx].size()) - 1, a, b, lx));
    }
    else{
        if (nivel[hpd[lx][0]] < nivel[hpd[ly][0]]){
            swap(x, y);
            swap (lx, ly);
        }
        ans = max (ans, Query(1, 0, int(hpd[lx].size()) - 1, 0, poz[x], lx));
        ans = max (ans, findMaxim(tata[hpd[lx][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)
        poz[i] = int(hpd[lant[i]].size()) - 1 - poz[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 << findMaxim(x, y) << "\n";
        else Update(1, 0, int(hpd[lant[x]].size()) - 1, poz[x], y, lant[x]);
        m--;
    }
    return 0;
}