Cod sursa(job #2632706)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 4 iulie 2020 14:54:59
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.17 kb
#include <bits/stdc++.h>
	
 
	
using namespace std;
	
int N, M;
	
const int INF = 0x3f3f3f3f;
	
const int Nmax = 100005;
	
 
	
vector<int> G[Nmax];
	
vector<int> lant[Nmax];
	
bitset<Nmax> used;
	
 
	
int care_lant[Nmax];
	
int tata_lant[Nmax];
	
int poz_lant[Nmax];
	
int greutate[Nmax];
	
int adancime[Nmax];
	
int valori[Nmax];
	
 
	
 
	
int pos, newX, A, B, answer, LC;
	
int nrl = 1;
	
 
	
class cmp{
	
public:
	
    bool operator()(const int &v1, const int &v2) const {
	
        return greutate[v1] > greutate[v2];
	
    }
	
};
	
 
	
class SegmentTree{
	
public:
	
    vector<int> range;
	
    void resize(int k) {
	
        range.resize(4 * k);
	
    }
	
    void build(int li, int lf ,int pz) {
	
        if(li == lf) {
	
            range[pz] = valori[lant[LC][li]];
	
            return;
	
        }
	
        int m = li + ((lf - li) >> 1);
	
        build(li, m , pz << 1);
	
        build(m + 1, lf, (pz << 1) | 1);
	
        range[pz] = max(range[pz << 1], range[(pz << 1) | 1]);
	
    }
	
    void update(int li, int lf, int pz) {
	
        if(li == lf) {
	
            range[pz] = newX;
	
            return;
	
        }
	
        int m = li + ((lf - li) >> 1);
	
        if(pos <= m)
	
            update(li, m, pz << 1);
	
        else
	
            update(m + 1, lf, (pz << 1) | 1);
	
 
	
        range[pz] = max(range[pz << 1], range[(pz << 1) | 1]);
	
    }
	
    void query(int li ,int lf, int pz) {
	
        if(A <= li && lf <= B) {
	
            answer = max(answer, range[pz]);
	
            return;
	
        }
	
        int m = li + ((lf - li) >> 1);
	
        if(A <= m)
	
            query(li, m, pz << 1);
	
        if(m < B)
	
            query(m + 1, lf, (pz << 1) | 1);
	
    }
	
};
	
SegmentTree Aint[Nmax];
	
 
	
void read()
	
{
	
    scanf("%d%d", &N, &M);
	
    for(int i = 1; i <= N; ++i){
	
        scanf("%d", &valori[i]);
	
    }
	
    for(int i = 1; i < N; ++i){
	
        int a, b;
	
        scanf("%d%d", &a, &b);
	
        G[a].push_back(b);
	
        G[b].push_back(a);
	
    }
	
}
	
 
	
void get_weight(int k)
	
{
	
    used[k] = 1;
	
    greutate[k] = 1;
	
    for(auto it : G[k])
	
        if(!used[it]) {
	
            adancime[it] = adancime[k] + 1;
	
            get_weight(it);
	
            greutate[k] += greutate[it];
	
        }
	
}
	
 
	
void descomp(int k)
	
{
	
    used[k] = 1;
	
    lant[nrl].push_back(k);
	
    care_lant[k] = nrl;
	
    poz_lant[k] = lant[nrl].size() - 1;
	
    for(auto it : G[k])
	
        if(!used[it]){
	
            if(lant[nrl].back() != k) {
	
                lant[++nrl].push_back(0);
	
                tata_lant[nrl] = k;
	
            }
	
            descomp(it);
	
        }
	
}
	
 
	
void Decompose()
	
{
	
    adancime[1] = 1;
	
    get_weight(1);
	
    used = 0;
	
    for(int i = 1; i <= N; ++i)
	
        sort(G[i].begin(), G[i].end(), cmp());
	
    lant[nrl].push_back(0);
	
    descomp(1);
	
}
	
 
	
void Build_trees()
	
{
	
    for(LC = 1; LC <= nrl; ++LC) {
	
        Aint[LC].resize(lant[LC].size());
	
        Aint[LC].build(1, lant[LC].size() - 1, 1);
	
    }
	
}
	
 
	
int Search(int x, int y)
	
{
	
    answer = -INF;
	
    while(care_lant[x] != care_lant[y])
	
    {
	
        if(adancime[tata_lant[care_lant[x]]] < adancime[tata_lant[care_lant[y]]])
	
            swap(x,y);
	
        if(care_lant[x] == 1)
	
            swap(x,y);
	
        LC = care_lant[x];
	
        A = 1;
	
        B = poz_lant[x];
	
        Aint[LC].query(1, lant[LC].size() - 1, 1);
	
        x = tata_lant[LC];
	
    }
	
    A = poz_lant[x];
	
    B = poz_lant[y];
	
    LC = care_lant[x];
	
    if(A > B) swap(A,B);
	
    Aint[LC].query(1, lant[LC].size() - 1, 1);
	
    return answer;
	
}
	
 
	
void Solve()
	
{
	
    int x,y,op,ch;
	
    for(int i = 1; i <= M; ++i) {
	
        scanf("%d%d%d", &op, &x, &y);
	
        if(op == 0)
	
        {
	
            LC = care_lant[x];
	
            newX = y;
	
            pos = poz_lant[x];
	
            Aint[LC].update(1, lant[LC].size() - 1, 1);
	
        }
	
        else
	
            printf("%d\n", Search(x,y));
	
    }
	
}
	
 
	
int main()
	
{
	
    freopen("heavypath.in", "r", stdin);
	
    freopen("heavypath.out", "w", stdout);
	
 
	
    read();
	
    Decompose();
	
    Build_trees();
	
    Solve();
	
 
	
    return 0;
	
}