Cod sursa(job #2217642)

Utilizator unknownpersonBidasca Carina Georgiana unknownperson Data 1 iulie 2018 12:11:02
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.34 kb
#include<bits/stdc++.h>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
const int N = 1<<17;


vector<int> v[N],P[N],p;
int n,q,i,x,y,t,z,Lg[N],V[N],niv[N],w[N],a[N],T[N],na,ST,DR,poz[N],DAD[N],Querry(int,int),QuerryA(int,int,int,int,int,int);
void df(int),AINT(int);
int main()
{
    f>>n>>q;
    for(i=1; i<=n; i++)
        f>>V[i];
    for(i=1; i<n; i++)
    {
        f>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    niv[1]=1;
    df(1);
    //am drumurile si constriuesc acum arborii de intervale
    for(i=1; i<=na; i++)
    {
        p.resize(0);
        DR=0;
        for(; P[i].size();)
        {
            x=P[i].back();
            P[i].pop_back();
            p.push_back(x);
            DR++;
            poz[x]=DR;
        }
        AINT(i);//construiesc arborele de intrvale corespunzator
    }
    for(; q; q--)
    {
        f>>t>>x>>y;
        if(!t)
        {
            i=a[x];
            int j=poz[x]+Lg[i]-1;
            P[i][j]=y;
            for(j/=2; j; j/=2)P[i][j]=max(P[i][2*j],P[i][2*j+1]);
            continue;
        }
        g<<Querry(x,y)<<'\n';

    }
    return 0;
}
void df(int nod)
{
    //setez greutatea nodului la 1;
    w[nod]=1;
    //daca nodul este frunza
    if(v[nod].size()==1&&nod!=1)
    {
        //construiesc un nou drum(care de fapt va fi un nou arbore de intervale)
        a[nod]=++na;
        P[na].push_back(nod);
        niv[nod]=niv[T[nod]]+1;
        DAD[a[nod]]=T[nod];
        return;
    }
    //daca nodul nu este frunza
    for(auto vec: v[nod])
    {
        //folosind tatal nodului calculez nivelul nodului
        if(vec==T[nod])
        {
            niv[nod]=niv[vec]+1;
            continue;
        }
        //pentru fii apelez df
        T[vec]=nod;
        df(vec);
        //folosesc greutatea fiilor pentru a calcula greutatea nodului
        w[nod]+=w[vec];
    }
    //incep a doua parcurgere sa determin fiul de greutate maxima
    int bst=0;
    for(auto vec: v[nod])
            //nu ma interezeaza tatal si fii de greutati mai mici decat cea mai buna de pana acum
        if(vec!=T[nod]&&w[vec]>bst)
        {
            //daca gasesc greutate mai mare updatez si redefinesc drumul la care lipesc nodul curent
            bst=w[vec];
            a[nod]=a[vec];
        }
    //pun nodul curent in arborele de intervale potrivit si actulaizez nodul la care se va lipi aceste
    P[a[nod]].push_back(nod);
    DAD[a[nod]]=T[nod];
}

int Querry(int x1,int x2)
{
    if(a[x1]==a[x2]) return QuerryA(a[x1],1,min(poz[x1],poz[x2]),max(poz[x1],poz[x2]),1,Lg[a[x1]]);
    if(niv[DAD[a[x1]]]<niv[DAD[a[x2]]])
        swap(x1,x2);
    return max(QuerryA(a[x1],1,1,poz[x1],1,Lg[a[x1]]),Querry(DAD[a[x1]],x2));
}
int QuerryA(int ar,int nod,int lo,int hi,int LO,int HI)
{
    if(lo>HI||hi<LO)return 0;
    if(lo<=LO&&HI<=hi)return P[ar][nod];
    int MI=(LO+HI)/2;
    return max(QuerryA(ar,2*nod,lo,hi,LO,MI),QuerryA(ar,2*nod+1,lo,hi,MI+1,HI));
}
void AINT(int i)
{
    int m=p.size();
    Lg[i]=1;
    while(Lg[i]<m)
        Lg[i]<<=1;
    P[i].resize(2*Lg[i]);
    fill(P[i].begin(),P[i].end(),0);
    int j=1;
    for(auto it:p)
    {
        P[i][j+Lg[i]-1]=V[it];
        j++;
    }
    for(j=Lg[i]-1;j>=1;j--)
        P[i][j]=max(P[i][2*j],P[i][2*j+1]);
}