zoukankan      html  css  js  c++  java
  • 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
    ");
                    else A.Link(A.data+x,A.data+y);
                }
                else if(type==2)
                {
                    if(x==y||!same) printf("-1
    ");
                    else A.Cut(A.data+x,A.data+y);
                }
                else if(type==3)
                {
                    if(!same) printf("-1
    ");
                    else A.Add(A.data+x,A.data+y,w);
                }
                else
                {
                    if(!same) printf("-1
    ");
                    else printf("%d
    ",A.MaxVal(A.data+x,A.data+y));
                }
            }
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    理解numpy.dot()
    Numpy数组操作
    numpy.rollaxis函数
    数组的分割
    数组的组合
    轴的概念
    Numpy数组解惑
    Django2.1.3 urls.py path模块配置
    ubuntu18.04创建虚拟环境时提示bash: /usr/local/bin/virtualenvwrapper.sh: 没有那个文件或目录 的解决办法
    对银行卡号进行验证(转)
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5755529.html
Copyright © 2011-2022 走看看