• URAL1553 Caves and Tunnels 树链剖分 动态树


    URAL1553 维护一棵树,随时修改某个节点的权值,询问(x,y)路径上权值最大的点。

    树是静态的,不过套动态树也能过,时限卡的严就得上树链剖分了。

    还是那句话 splay的核心是splay(x) LCT的核心是access(x)

    SPOJ OTOCI的代码改了两行就过了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int MaxNode=131000;
    
    int Lch[MaxNode];
    int Rch[MaxNode];
    int Pnt[MaxNode];
    int Data[MaxNode];
    int Sum[MaxNode];
    int Rev[MaxNode];
    int List[MaxNode];
    int maxv[MaxNode];
    int Total;
    
    inline bool isRoot(int t){
        return (!Pnt[t]||(Lch[Pnt[t]]!=t&&Rch[Pnt[t]]!=t));
    }
    inline void Update(int cur){
        maxv[cur]=Data[cur];
        if(Lch[cur]!=0)maxv[cur]=max(maxv[cur],maxv[Lch[cur]]);
        if(Rch[cur]!=0)maxv[cur]=max(maxv[cur],maxv[Rch[cur]]);
    }
    void Reverse(int cur){
        if (!Rev[cur]) return;
        swap(Lch[cur],Rch[cur]);
        Rev[Lch[cur]]^=1;
        Rev[Rch[cur]]^=1;
        Rev[cur]=0;
    }
    void LeftRotate(int cur){
        if (isRoot(cur)) return;
        int pnt=Pnt[cur],anc=Pnt[pnt];
        Lch[pnt]=Rch[cur];
        if (Rch[cur]) Pnt[Rch[cur]]=pnt;
        Rch[cur]=pnt;
        Pnt[pnt]=cur;
        Pnt[cur]=anc;
        if (anc){
            if (Lch[anc]==pnt) Lch[anc]=cur;
            else if (Rch[anc]==pnt) Rch[anc]=cur;
        }
        Update(pnt);
        Update(cur);
    }
    void RightRotate(int cur){
        if (isRoot(cur)) return;
        int pnt=Pnt[cur],anc=Pnt[pnt];
        Rch[pnt]=Lch[cur];
        if (Lch[cur]) Pnt[Lch[cur]]=pnt;
        Lch[cur]=pnt;
        Pnt[pnt]=cur;
        Pnt[cur]=anc;
        if (anc){
            if (Rch[anc]==pnt) Rch[anc]=cur;
            else if (Lch[anc]==pnt) Lch[anc]=cur;
        }
        Update(pnt);
        Update(cur);
    }
    void Splay(int cur){
        int pnt,anc;
        List[++Total]=cur;
        for (int i=cur;!isRoot(i);i=Pnt[i]) List[++Total]=Pnt[i];
        for (;Total;--Total)
            if (Rev[List[Total]]) Reverse(List[Total]);
        while (!isRoot(cur)){
            pnt=Pnt[cur];
            if (isRoot(pnt)){// 父亲是根结点,做一次旋转
                if (Lch[pnt]==cur) LeftRotate(cur);
                else RightRotate(cur);
            }
            else{
                anc=Pnt[pnt];
                if (Lch[anc]==pnt){
                    if (Lch[pnt]==cur) LeftRotate(pnt),LeftRotate(cur);// 一条线
                    else RightRotate(cur),LeftRotate(cur);// 相反两次
                }
                else{
                    if (Rch[pnt]==cur) RightRotate(pnt),RightRotate(cur);// 一条线
                    else LeftRotate(cur),RightRotate(cur);// 相反两次
                }
            }
        }
    }
    int Expose(int u){
        int v=0;
        for (;u;u=Pnt[u]) Splay(u),Rch[u]=v,v=u,Update(u);
        for (;Lch[v];v=Lch[v]);
        return v;
    }
    void Modify(int x,int d){
        Splay(x);
        Data[x]=d;
        Update(x);
    }
    int Query(int x,int y){
        int rx=Expose(x),ry=Expose(y);
        if (rx==ry){
            for (int u=x,v=0;u;u=Pnt[u]){
                Splay(u);
                if (!Pnt[u]) return max(max(maxv[Rch[u]],Data[u]),maxv[v]);
                Rch[u]=v;
                Update(u);
                v=u;
            }
        }
        return -1;
    }
    bool Join(int x,int y){
        int rx=Expose(x),ry=Expose(y);
        if (rx==ry) return false;
        else{
            Splay(x);
            Rch[x]=0;
            Rev[x]=1;
            Pnt[x]=y;
            Update(x);
            return true;
        }
    }
    void Cut(int x){
        if (Pnt[x]){
            Expose(x);
            Pnt[Lch[x]]=0;
            Lch[x]=0;
            Update(x);
        }
    }
    int n,Q;
    
    void init(){
        Total=0;
        memset(Rev,0,sizeof(Rev));
        memset(Pnt,0,sizeof(Pnt));
        memset(Lch,0,sizeof(Lch));
        memset(Rch,0,sizeof(Rch));
        memset(Sum,0,sizeof(Sum));
        memset(Data,0,sizeof(Data));
        memset(maxv,0,sizeof(maxv));
    }
    char cmd[22];
    int main()
    {   freopen("t.txt","r",stdin);
        init();
        scanf("%d",&n);
        for(int i=0;i<n-1;i++)
        	{
        	 int a,b;
        	 scanf("%d%d",&a,&b);
        	 Join(a,b);
    		}
        scanf("%d",&Q);
        while (Q--){
            int x,y;
            scanf("%s%d%d",cmd,&x,&y);
            if (cmd[0]=='I'){
                Modify(x,Data[x]+y);
            }
            if (cmd[0]=='G'){
                printf("%d",Query(x,y));
                if(Q>0)printf("
    ");
            }
    
            
        }
        return 0;
    }
    

      

  • 相关阅读:
    Redis指令(2) ------String
    Redis指令(1) ------常用指令
    Redis数据类型
    Python set集合
    Python random 模块
    Python random 模块
    Python time 模块
    Python sys模块
    Python 递归函数
    Python 局部变量和全局变量
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6597097.html
Copyright © 2020-2023  润新知