hdu4010-Query on The Trees(lct分裂合并加值查询最大值)

代码

#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int INF=1e9+7;
const int maxn=300005;
int val[maxn];
int N,Q;
vector<int> G[maxn];
struct lct
{
    lct *fa,*son[2];
    int rev,v,mv,add;
};
struct LCT
{
    lct data[maxn];
    lct *null;
    void init(int Size=maxn-1) //初始化
    {
        null=data; //null指向首元素
        for(int i=0;i<=Size;i++)
        {
            data[i].son[0]=data[i].son[1]=data[i].fa=null;
            data[i].v=data[i].mv=val[i];
            data[i].rev=data[i].add=0;
        }
        null->v=null->mv=-INF;
    }
    void dfs(int u,int fa)
    {
        data[u].fa=data+fa;
        int Size=G[u].size();
        for(int i=0;i<Size;i++)
        {
            int v=G[u][i];
            if(v==fa) continue;
            dfs(v,u);
        }
    }
    void push_add(lct* x,int add)
    {
        if(x==null) return;
        x->v+=add;
        x->add+=add;
        x->mv+=add;
    }
    void push_rev(lct* x)
    {
        if(x==null) return;
        x->rev=!x->rev;
        swap(x->son[0],x->son[1]);
    }
    void pushdown(lct* x)
    {
        if(x->add!=0)
        {
            push_add(x->son[0],x->add);
            push_add(x->son[1],x->add);
            x->add=0;
        }
        if(x->rev)
        {
            push_rev(x->son[0]);
            push_rev(x->son[1]);
            x->rev=0;
        }
    }
    void pushup(lct* x)
    {
        if(x==null) return;
        x->mv=x->v;
        x->mv=max(x->mv,x->son[0]->mv);
        x->mv=max(x->mv,x->son[1]->mv);
    }
    bool Same(lct* x,lct* &y) //判断x和x的父亲是否在同一树里
    {
        return (y=x->fa)!=null&&(y->son[0]==x||y->son[1]==x);
    }
    void Rotate(lct* x,int d) //翻转
    {
        lct* y=x->fa; //x的父亲
        y->son[d^1]=x->son[d];
        if(x->son[d]!=null) x->son[d]->fa=y; //x的子节点的父亲指向y
        x->fa=y->fa;  //连接
        if(y->fa->son[0]==y) x->fa->son[0]=x;
        else if(y->fa->son[1]==y) x->fa->son[1]=x;
        x->son[d]=y;
        y->fa=x;
    }
    void Splay(lct* x)
    {
        pushdown(x); //清除标记
        lct* y;
        while(Same(x,y)) //没有到树的最顶点
        {
            pushdown(y);
            pushdown(x);
            Rotate(x,y->son[0]==x); //翻转
            pushup(y);
            pushup(x);
        }
    }
    lct* Access(lct* u)  //打通路径,返回的是根
    {
        lct *v=null;
        for(;u!=null;u=u->fa)
        {
            Splay(u);
            u->son[1]=v;
            pushup(v=u);
        }
        return v;
    }
    lct* GetRoot(lct* x) //得到根
    {
        for(x=Access(x);pushdown(x),x->son[0]!=null;x=x->son[0]) pushup(x);
        return x;
    }
    void MakeRoot(lct* x) //使x成为根
    {
        Access(x);
        Splay(x);
        push_rev(x);
    }
    void Link(lct* x,lct* y) //连接两个点
    {
        MakeRoot(x);
        x->fa=y;
        Access(x);
    }
    void Cut(lct* x,lct* y) //断开两个点
    {
        MakeRoot(x);
        Access(y);
        Splay(y);
        y->son[0]->fa=null;
        y->son[0]=null;
    }
    void Add(lct* x,lct* y,int add)
    {
        MakeRoot(x);
        push_add(Access(y),add);
    }
    int MaxVal(lct* x,lct* y)
    {
        MakeRoot(x);
        Access(y);
        Splay(y);
        return y->mv;
    }
}A;
int main()
{
    while(scanf("%d",&N)!=EOF)
    {
        for(int i=0;i<=N;i++) G[i].clear();
        int x,y;
        for(int i=1;i<N;i++)
        {
            scanf("%d%d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        val[0]=0;
        for(int i=1;i<=N;i++) scanf("%d",&val[i]);
        A.init(N);
        A.dfs(1,0);
        int type,w;
        scanf("%d",&Q);
        while(Q--)
        {
            scanf("%d",&type);
            if(type==3) scanf("%d",&w);
            scanf("%d%d",&x,&y);
            bool same=(A.GetRoot(A.data+x)==A.GetRoot(A.data+y));
            if(type==1)
            {
                if(same) printf("-1\n");
                else A.Link(A.data+x,A.data+y);
            }
            else if(type==2)
            {
                if(x==y||!same) printf("-1\n");
                else A.Cut(A.data+x,A.data+y);
            }
            else if(type==3)
            {
                if(!same) printf("-1\n");
                else A.Add(A.data+x,A.data+y,w);
            }
            else
            {
                if(!same) printf("-1\n");
                else printf("%d\n",A.MaxVal(A.data+x,A.data+y));
            }
        }
        printf("\n");
    }
    return 0;
}
View Code

 

posted @ 2016-08-10 09:49  wust_ouyangli  阅读(191)  评论(0编辑  收藏  举报