Cod sursa(job #1536186)

Utilizator dobrebogdanDobre Bogdan Mihai dobrebogdan Data 25 noiembrie 2015 20:15:16
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.77 kb
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int nmax=100005;
vector<int> ve[nmax],drum[nmax];
bool be[nmax],viz[nmax];
int ndr,co[nmax],lv[nmax],ap[nmax];
int we[nmax],v[nmax],po[nmax],ta[nmax];
struct nod
{
    int ma,st,dr;
    nod * fiust,*fiudr;
    nod()
    {
        fiust=fiudr=NULL;
        ma=0;
    }
};
nod * ai[nmax];
void init(int x)
{
    we[x]=1;
    for(int i=ve[x].size()-1; i>=0; i--)
        if(lv[ve[x][i]]==0)
        {
            ta[ve[x][i]]=x;
            lv[ve[x][i]]=lv[x]+1;
            init(ve[x][i]);
            we[x]+=we[ve[x][i]];
        }

}
void baga(int x)
{
    ndr++;
    int i,j,l=0;
    viz[x]=1;
    while(x!=0)
    {
        drum[ndr].push_back(x);
        po[x]=l;
        ap[x]=ndr;
        l++;
        j=0;
        for(i=ve[x].size()-1; i>=0; i--)
            if(viz[ve[x][i]]==0)
            {
                if(j==0 || we[ve[x][i]]>we[j])
                    j=ve[x][i];
            }
        x=j;
        viz[x]=1;
    }
}
void prep(nod * root)
{
    if(root->st!=root->dr)
    {
        int mi=(root->st+root->dr)/2;
        root->fiust=new nod();
        root->fiust->st=root->st;
        root->fiust->dr=mi;
        prep(root->fiust);
        root->fiudr=new nod();
        root->fiudr->st=mi+1;
        root->fiudr->dr=root->dr;
        prep(root->fiudr);
    }
}
void update(nod * root,int x,int val)
{
    if(x==root->st && x==root->dr)
    {
        root->ma=val;
    }
    else
    {
        int mi=(root->st+root->dr)/2;
        if(x<=mi)
            update(root->fiust,x,val);
        else if(x>mi)
            update(root->fiudr,x,val);
        root->ma=max(root->fiust->ma,root->fiudr->ma);
    }
}
int query(nod * root,int x,int y)
{
    int ma=0;
    int mi=(root->st+root->dr)/2;
    if(x==root->st && y==root->dr)
    {
        ma=root->ma;
    }
    else
    {
        if(y<=mi)
            ma=query(root->fiust,x,y);
        else if(x>mi)
            ma=query(root->fiudr,x,y);
        else
        {
            ma=max(ma,query(root->fiust,x,mi));
            ma=max(ma,query(root->fiudr,mi+1,y));
        }
    }
    return ma;
}
int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    int n,t,i,j,x,y,q,st,dr,ti,ma;
    scanf("%d%d",&n,&t);
    for(i=1; i<=n; i++)
        scanf("%d",&v[i]);
    for(i=1; i<n; i++)
    {
        scanf("%d%d",&x,&y);
        ve[x].push_back(y);
        ve[y].push_back(x);
    }
    lv[1]=1;
    init(1);
    st=dr=1;
    co[1]=1;
    be[1]=1;
    ndr=0;
    while(st<=dr)
    {
        x=co[st];
        for(i=ve[x].size()-1; i>=0; i--)
            if(lv[ve[x][i]]==lv[x]+1)
            {
                dr++;
                co[dr]=ve[x][i];
            }
        if(viz[x]==0)
            baga(x);
        st++;
    }
    for(i=1; i<=ndr; i++)
    {
        ai[i]=new nod();
        ai[i]->st=0;
        ai[i]->dr=drum[i].size()-1;
        prep(ai[i]);
    }
    for(i=1;i<=n;i++)
    {
        update(ai[ap[i]],po[i],v[i]);
    }
    for(q=1; q<=t; q++)
    {
        scanf("%d%d%d",&ti,&x,&y);
        if(ti==1)
        {
            ma=0;
            while(ap[x]!=ap[y] && (x!=0 || y!=0))
            {
                if(lv[drum[ap[x]][0]]<lv[drum[ap[y]][0]])
                    swap(x,y);
                ma=max(ma,query(ai[ap[x]],0,po[x]));
                x=ta[drum[ap[x]][0]];
            }
           if(x!=0 && y!=0)
           {
            if(lv[x]<lv[y])
                swap(x,y);
            ma=max(ma,query(ai[ap[x]],po[y],po[x]));
           }
                       printf("%d\n",ma);
        }
        else
            update(ai[ap[x]],po[x],y);

    }
    return 0;
}