Cod sursa(job #2120687)

Utilizator tifui.alexandruTifui Ioan Alexandru tifui.alexandru Data 2 februarie 2018 19:31:15
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.56 kb
#include <bits/stdc++.h>
#define Nmax 100001
#define ls (((nod+1)<<1)-1)
#define rs ((nod+1)<<1)
#define DIM 700000
using namespace std;
char buffer[DIM];
int cursor=DIM-1;
void read(int &x)
{
    x=0;
    while(!isdigit(buffer[cursor]))
        if(++cursor==DIM)
        {
            cursor=0;
            fread(buffer,1,DIM,stdin);
        }
    while(isdigit(buffer[cursor]))
    {
        x=x*10+buffer[cursor]-'0';
        if(++cursor==DIM)
        {
            cursor=0;
            fread(buffer,1,DIM,stdin);
        }
    }
}
int v[Nmax],nr_chain[Nmax],poz[Nmax],lvl[Nmax],weight[Nmax],t[Nmax];
list <int> arb[Nmax];
vector <int> chain[Nmax];
vector <int> Aint[Nmax];
int N,changed,nr_arb,lsh,rsh;
void DFS(int x)
{
    int nr=0,nod=0;
    for(list <int> :: iterator it=arb[x].begin();it!=arb[x].end();++it)
        if(!lvl[*it])
        {
            nr++;
            t[*it]=x;
            lvl[*it]=lvl[x]+1;
            DFS(*it);
            if(weight[*it]>weight[nod])
                nod=*it;
        }
    weight[x]=nr+1;
    if(nr)
    {
        nr_chain[x]=nr_chain[nod];
        chain[nr_chain[x]].push_back(x);
    }
    else
    {
        nr_chain[x]=++N;
        chain[N].push_back(x);
    }
}
inline bool cmp(const int &x, const int &y)
{
    return lvl[x]<lvl[y];
}
void build(int p, int q, int nod)
{
    if(p==q)
        Aint[nr_arb][nod]=v[chain[nr_arb][p]];
    else
    {
        int m=(p+q)>>1;
        build(p,m,ls);
        build(m+1,q,rs);
        Aint[nr_arb][nod]=max(Aint[nr_arb][ls],Aint[nr_arb][rs]);
    }
}
void update(int p, int q, int nod)
{
    if(p==q) Aint[nr_arb][nod]=v[chain[nr_arb][p]];
    else
    {
        int m=(p+q)>>1;
        if(changed<=m) update(p,m,ls);
        else update(m+1,q,rs);
        Aint[nr_arb][nod]=max(Aint[nr_arb][ls],Aint[nr_arb][rs]);
    }
}
int query(int p, int q, int nod)
{
    if(lsh<=p and q<=rsh) return Aint[nr_arb][nod];
    else
    {
        int m=(p+q)>>1,max1=-INT_MAX,max2=-INT_MAX;
        if(lsh<=m) max1=query(p,m,ls);
        if(m<rsh) max2=query(m+1,q,rs);
        return max(max1,max2);
    }
}
int heavy_path_query(int x, int y)
{
    int maxx=-1;
    while(nr_chain[x]!=nr_chain[y])
    {
        if(lvl[chain[nr_chain[x]][0]]<lvl[chain[nr_chain[y]][0]]) swap(x,y);
        lsh=0;
        rsh=poz[x];
        nr_arb=nr_chain[x];
        maxx=max(maxx,query(0,chain[nr_arb].size()-1,0));
        x=t[chain[nr_chain[x]][0]];
    }
    nr_arb=nr_chain[x];
    lsh=poz[x];
    rsh=poz[y];
    if(lsh>rsh) swap(lsh,rsh);
    return max(maxx,query(0,chain[nr_arb].size()-1,0));
}
int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    int n,Q,i,j,x,y,op;
    read(n);
    read(Q);
    for(i=1;i<=n;i++)
        read(v[i]);
    for(i=1;i<n;i++)
    {
        read(x);
        read(y);
        arb[x].push_back(y);
        arb[y].push_back(x);
    }
    lvl[1]=1;
    DFS(1);
    for(i=1;i<=N;i++)
    {
        sort(chain[i].begin(),chain[i].end(),cmp);
        for(j=0;j<(int)chain[i].size();j++)
            poz[chain[i][j]]=j;
        Aint[i].resize(4*chain[i].size());
        nr_arb=i;
        build(0,chain[i].size()-1,0);
    }
    while(Q--)
    {
        read(op);
        read(x);
        read(y);
        if(!op)
        {
            v[x]=y;
            nr_arb=nr_chain[x];
            changed=poz[x];
            update(0,chain[nr_arb].size()-1,0);
        }
        else
            printf("%d\n",heavy_path_query(x,y));
    }

    return 0;
}