Cod sursa(job #1404785)

Utilizator mihail.jianuJianu Mihail mihail.jianu Data 28 martie 2015 15:55:59
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.07 kb
#include<cstdio>
#include<vector>
#include<cstring>
int max2(int a,int b){
    if(a>b)
        return a;
    return b;
}
int min2(int a,int b){
    if(a<b)
        return a;
    return b;
}
void change(int&x,int&y){
    int aux=x;
    x=y;
    y=aux;
}
using namespace std;
const int N=100000;
class Lant{
    public:
        int start;
        vector<int>v;
        int l;
        Lant(){
        }
        Lant(int s,int ll){
            start=s;
            l=ll;
        }
};
vector<int>g[N+1];
Lant lant[N+1];
int niv[N+1];
int father[N+1];
int whose[N+1];
int imp[N+1];
int subtree[N+1];
bool vis[N+1];
int cost[N+1];
int grand[N+1];
int v[N+1];
int t[4*N+1];
int n,k,vv,pp;
int res;
int left,right;
/// ///////////////////////////////////////////////////////////
void build(int pos,int st,int dr){
    if(st==dr){
        t[pos]=cost[v[st]];
        return;
    }
    int m=(st+dr)/2;
    build(pos*2,st,m);
    build(pos*2+1,m+1,dr);
    t[pos]=max2(t[pos*2],t[pos*2+1]);
}
void update(int pos,int st,int dr){
    if(st==dr){
        t[pos]=vv;
        return;
    }
    int m=(st+dr)/2;
    if(pp<=m)
        update(pos*2,st,m);
    else
        update(pos*2+1,m+1,dr);
    t[pos]=max2(t[pos*2],t[pos*2+1]);
}
int query(int pos,int st,int dr){
    if(dr<left||st>right)
        return 0;
    if(left<=st&&dr<=right)
        return t[pos];
    int m=(st+dr)/2;
    return max2(query(pos*2,st,m),query(pos*2+1,m+1,dr));
}
/// ////////////////////////////////////////////////////////////////
void dfs1(int dad){
    vis[dad]=true;
    int maxx=0;
    subtree[dad]=1;
    for(unsigned int i=0;i<g[dad].size();i++){
        int son=g[dad][i];
        if(!vis[son]){
            father[son]=dad;
            niv[son]=niv[dad]+1;
            dfs1(son);
            subtree[dad]+=subtree[son];
            if(subtree[son]>maxx){
                maxx=subtree[son];
                whose[dad]=whose[son];
            }
        }
    }
    if(g[dad].size()==1&&dad!=1)
        whose[dad]=++k;
    lant[whose[dad]].v.push_back(dad);
}
void dfs2(int dad){
    if(!grand[dad]){
        imp[dad]=1;
        grand[dad]=dad;
    }
    vis[dad]=true;
    for(unsigned int i=0;i<g[dad].size();i++){
        int son=g[dad][i];
        if(!vis[son]){
            if(whose[dad]==whose[son]){
                imp[son]=imp[dad]+1;
                grand[son]=grand[dad];
            }
            dfs2(son);
        }
    }
}
void set_arbint(){
    lant[0].start=1;
    int x=0;
    for(int i=1;i<=k;i++){
        lant[i].start=lant[i-1].start+lant[i-1].l;
        lant[i].l=lant[i].v.size();
        for(unsigned int j=lant[i].v.size();j!=0;j--)
            v[++x]=lant[i].v[j-1];
    }
    build(1,1,n);
}
int trans(int p){
    int r=lant[whose[p]].start;
    r+=imp[p]-1;
    return r;
}
void heavy_update(int p,int vl){
    cost[p]=vl;
    pp=trans(p);
    vv=vl;
    update(1,1,n);
}
int heavy_query(int x,int y){
    res=0;
    if(niv[grand[x]]>niv[grand[y]])
        change(x,y);
    while(true){
        if(grand[x]==grand[y]){
            left=min2(trans(x),trans(y));
            right=max2(trans(x),trans(y));
            res=max2(res,query(1,1,n));
            break;
        }
        left=trans(grand[y]);
        right=trans(y);
        res=max2(res,query(1,1,n));
        y=father[grand[y]];
        if(niv[grand[x]]>niv[grand[y]])
            change(x,y);
    }
    return res;
}
int main(){
    int q;
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
        scanf("%d",&cost[i]);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    niv[1]=1;
    dfs1(1);
    memset(vis,0,sizeof(vis));
    dfs2(1);
    set_arbint();
    while(q--){
        int t,x,y;
        scanf("%d%d%d",&t,&x,&y);
        if(t==0)
            heavy_update(x,y);
        else
            printf("%d\n",heavy_query(x,y));
    }
    return 0;
}