• bzoj3159: 决战


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3159

    思路:题解与标程在此:http://tieba.baidu.com/p/2307619154

    首先链翻转显然不能直接在lct上打翻转标记,那样是在翻转链的深度,不是翻转链上的值

    于是就有了一种做法,写两个splay,一个维护权值,一个维护形态

    每棵形态splay和对应值splay总保证点数相同,这样对于权值翻转我们就可以只在值splay上翻转,形态splay不变即可

    关键是维护形态splay到值splay的指针

    最重要的一点就是维护形态splay的根到对应值splay的根的指针

    题解已经讲的比较清楚了,但是具体细节比较多

    主要是在access的同时维护这个指针(因为access会导致splay的分离和合并,一定要想清楚)

    形态splay执行splay操作时也要记得把原来根的指针传递给现在splay上来的新根

    总之就是各种错,各种坑,改了不下十个错误才改对


    另外我怎么觉得跨过LCA的链也是可以翻转的,这可是动态树啊,makeroot一下,access一下不就提出了这个链吗,代码不会有任何区别。也许是有不为人知的阴谋


    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ls ch[x][0]
    #define rs ch[x][1]
    const int maxn=100010,maxm=maxn<<1;
    typedef long long ll;
    using namespace std;
    int n,R,cas,Q,pre[maxm],now[maxn],son[maxm],tot;char op[12];
    void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
     
    struct Tsplay{
        int siz[maxn],ch[maxn][2],fa[maxn],tag[maxn];ll mins[maxn],maxs[maxn],sum[maxn],val[maxn];bool rev[maxn];
        int isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
        int which(int x){return ch[fa[x]][1]==x;}
        void init(int x,int v){siz[x]=1,mins[x]=maxs[x]=sum[x]=val[x]=v;}
        void update(int x){
            siz[x]=1,mins[x]=maxs[x]=sum[x]=val[x];
            if (ls) siz[x]+=siz[ls],mins[x]=min(mins[x],mins[ls]),maxs[x]=max(maxs[x],maxs[ls]),sum[x]+=sum[ls];
            if (rs) siz[x]+=siz[rs],mins[x]=min(mins[x],mins[rs]),maxs[x]=max(maxs[x],maxs[rs]),sum[x]+=sum[rs];
        }
        void add(int x,int v){if (x) sum[x]+=1ll*v*siz[x],tag[x]+=v,mins[x]+=v,maxs[x]+=v,val[x]+=v;}
        void rever(int x){swap(ls,rs),rev[x]^=1;}
        void down(int x){
            if (tag[x]) add(ls,tag[x]),add(rs,tag[x]),tag[x]=0;
            if (rev[x]) rever(ls),rever(rs),rev[x]=0;
        }
        int relax(int x){
            int anc=isroot(x)?x:relax(fa[x]);
            down(x);return anc;
        }
        void rotate(int x){  
            int y=fa[x],z=fa[y],nx=which(x),ny=which(y);  
            fa[ch[x][!nx]]=y,ch[y][nx]=ch[x][!nx];  
            fa[x]=z;if (!isroot(y)) ch[z][ny]=x;//这行要放在下一行前,不然isroot会错
            fa[y]=x,ch[x][!nx]=y;update(y);
        }
        void splay(int x){
            relax(x);
            while(!isroot(x)){
                int y=fa[x];
                if (isroot(y)) rotate(x);
                else if (which(x)==which(y)) rotate(y),rotate(x);
                else rotate(x),rotate(x);
            }
            update(x);
        }
        int findrt(int &x){while (fa[x]) x=fa[x];return x;}
        int find(int &x,int rank){
            for (;;){
            	down(x);
                if (rank<=siz[ls]) x=ls;
                else if (rank==siz[ls]+1) return x;
                else rank-=(siz[ls]+1),x=rs;
            }
        }
    }val;
    
    struct Tlct{
        int siz[maxn],ch[maxn][2],fa[maxn],rt[maxn],q[maxn];bool rev[maxn];
        int isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
        int which(int x){return ch[fa[x]][1]==x;}
        void init(int x,int v,int ff){rt[x]=x,siz[x]=1,fa[x]=ff,val.init(x,v);}
        void update(int x){siz[x]=siz[ls]+siz[rs]+1;}
        void rever(int x){swap(ls,rs),rev[x]^=1;}
        void down(int x){if (rev[x]) rever(ls),rever(rs),rev[x]=0;}
    	int relax(int x){
            int anc=isroot(x)?x:relax(fa[x]);
            down(x);return anc;
        }
        void rotate(int x){  
            int y=fa[x],z=fa[y],nx=which(x),ny=which(y);  
            fa[ch[x][!nx]]=y,ch[y][nx]=ch[x][!nx];  
            fa[x]=z;if (!isroot(y)) ch[z][ny]=x;  
            fa[y]=x,ch[x][!nx]=y;update(y);  
        }
        void splay(int x){
        	int anc=relax(x);
            rt[x]=rt[anc];
            while(!isroot(x)){
                int y=fa[x];
                if (isroot(y)) rotate(x);
                else if (which(x)==which(y)) rotate(y),rotate(x);
                else rotate(x),rotate(x);
            }
            update(x);
        }
        void access(int x){
            for (int y=0;x;y=x,x=fa[x]){
                splay(x);int x2=val.findrt(rt[x]);int y2=val.findrt(rt[y]);
                if (!y) y2=0;//这句特判一定要加,因为rt【0】会被改动
                val.find(x2,siz[ls]+1),val.splay(x2),rt[x]=x2;
                rt[rs]=val.ch[x2][1],val.fa[val.ch[x2][1]]=0,val.ch[x2][1]=y2,val.fa[y2]=x2,val.update(x2);
                rs=y,update(x);
            }
        }
        void makeroot(int x){access(x),splay(x),rever(x),val.rever(rt[x]);}
        void split(int x,int y){makeroot(x),access(y);}
        void dfs(int x,int ff){
            init(x,0,ff);
            for (int y=now[x];y;y=pre[y])
                if (son[y]!=ff) dfs(son[y],x);
        }
    }lct;
    
    int main(){
        scanf("%d%d%d",&n,&Q,&R);
        for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
        lct.dfs(R,0);
        for (int i=1,x,y,z;i<=Q;i++){
            scanf("%s%d%d",op+1,&x,&y);
            lct.split(x,y);int vy=val.findrt(lct.rt[y]);//SB错误,y打成x
            if (op[3]=='c') scanf("%d",&z),val.add(vy,z);
            else if (op[3]=='m') printf("%lld
    ",val.sum[vy]);
            else if (op[3]=='j') printf("%lld
    ",val.maxs[vy]);
            else if (op[3]=='n') printf("%lld
    ",val.mins[vy]);
            else val.rever(vy);
        }
        return 0;
    }



  • 相关阅读:
    笔记3
    笔记
    指令操作、例子
    python文件操作
    pandas处理excel
    Flask资源
    ImportError: DLL load failed while importing _ssl: 找不到指定的模块。 Failed
    WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
    selenium 安装与 chromedriver安装
    ubuntu 更换清华源
  • 原文地址:https://www.cnblogs.com/thythy/p/5493451.html
Copyright © 2020-2023  润新知