zoukankan      html  css  js  c++  java
  • 平衡树板子

    Achen大佬说不要沉迷数据结构否则智商会降低的。

    从省选考完后就开始学treap,首先是自己yy了一个打了两百多行,然后debug了2个月还是3个月记不清了。

    最后弃疗,去找了网上别人的代码抄了一遍。

    noip考完后补常规的一段时间,羡慕Achen能20分钟打出一个treap模板,于是自己也开始走上打板子的不归路。

    到了后来可以10分钟左右打出一个结构体版的treap,看了Achen的数组版treap,觉得自己结构体版的太不优秀啦,于是就换成数组版的。

    然后现在有几周没有碰过treap,感觉又不会打了。。。。不过还好,大概看一下又想起来了。

    先放板子,还不会打题。

    结构体版:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    using namespace std;
    const int maxn=100000+10;
    int n,tot=0,ans1,ans2,root;
    
    int aa,ff;char cc;
    int read() {
        aa=0;ff=1;cc=getchar();
        while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        return aa*ff;
    }
    
    struct Node{
        int num,rnd,son[2],sum,x;
    }node[maxn];
    
    void rotate(int &pos,int p) {
        int s=node[pos].son[p];
        node[s].sum=node[pos].sum;
        node[pos].son[p]=node[s].son[!p];
        node[s].son[!p]=pos;
        node[pos].sum=node[pos].x+node[node[pos].son[0]].sum+node[node[pos].son[1]].sum;
        pos=s;
    }
    
    void add(int &pos,int x) {
        if(!pos) {
            pos=++tot;node[pos].num=x;node[pos].rnd=rand();
            node[pos].sum=node[pos].x=1;
            return ;
        }
        node[pos].sum++;
        if(node[pos].num==x) {
            node[pos].x++; return;
        }
        int p=x>node[pos].num;
        add(node[pos].son[p],x);
        if(node[node[pos].son[p]].rnd<node[pos].rnd) rotate(pos,p);
    }
    
    void del(int &pos,int x) {
        if(!pos) return;
        if(node[pos].num==x) {
            if(node[pos].x>1) {
                node[pos].x--;node[pos].sum--;return;
            }
            if(node[pos].son[0]*node[pos].son[1]==0) {
                pos=node[pos].son[0]+node[pos].son[1]; return;
            }
            int p= node[node[pos].son[1]].rnd<node[node[pos].son[0]].rnd;
            rotate(pos,p);
            node[pos].sum--;
            del(node[pos].son[!p],x);
        }
        else {
            node[pos].sum--;
            if(node[pos].num>x) del(node[pos].son[0],x);
            else del(node[pos].son[1],x);
        }
    }
    
    int qrank(int pos,int x) {
        if(node[pos].num==x) return node[node[pos].son[0]].sum+1;
        if(node[pos].num>x) return qrank(node[pos].son[0],x);
        return node[node[pos].son[0]].sum+node[pos].x+qrank(node[pos].son[1],x);
    }
    
    int qnum(int pos,int x) {
        if(x>node[node[pos].son[0]].sum&&x<=node[node[pos].son[0]].sum+node[pos].x) return node[pos].num;
        if(x<=node[node[pos].son[0]].sum) return qnum(node[pos].son[0],x);
        return qnum(node[pos].son[1],x-node[pos].x-node[node[pos].son[0]].sum);
    }
    
    void q1(int pos,int x) {
        if(!pos) return;
        if(x>node[pos].num) {
            ans1=node[pos].num;
            q1(node[pos].son[1],x);
        }
        else q1(node[pos].son[0],x);
    }
    
    void q2(int pos,int x) {
        if(!pos) return;
        if(x<node[pos].num) {
            ans2=node[pos].num;
            q2(node[pos].son[0],x);
        }
        else q2(node[pos].son[1],x);
    }
    
    int main() {
        srand((unsigned)time(NULL));
        n=read();
        int opt,x,y;
        for(int i=1;i<=n;++i) {
            opt=read();x=read();
            if(opt==1) add(root,x);
            else if(opt==2) del(root,x);
            else if(opt==3) printf("%d
    ",qrank(root,x));
            else if(opt==4) printf("%d
    ",qnum(root,x));
            else if(opt==5) q1(root,x),printf("%d
    ",ans1);
            else q2(root,x),printf("%d
    ",ans2);
        }
        return 0;
    }

    数组版:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=1e5+10;
    int n,tot,root,ans;
    int sum[maxn],num[maxn],rnd[maxn],fx[maxn],son[maxn][2];
    
    int aa,ff;char cc;
    int read() {
        aa=0;cc=getchar();ff=1;
        while(cc<'0'||cc>'9') {
            if(cc=='-') ff=-1;
            cc=getchar();
        }
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        return aa*ff;
    }
    
    void rotate(int &pos,int p) {
        int s=son[pos][p];
        sum[s]=sum[pos];
        son[pos][p]=son[s][!p];
        son[s][!p]=pos;
        sum[pos]=sum[son[pos][0]]+sum[son[pos][1]]+fx[pos];
        pos=s;
    }
    
    void add(int &pos,int x) {
        if(!pos) {
            pos=++tot;
            num[pos]=x;
            rnd[pos]=rand();
        }
        sum[pos]++;
        if(num[pos]==x) {
            fx[pos]++;
            return;
        }
        int p=x>num[pos];
        add(son[pos][p],x);
        if(rnd[son[pos][p]]<rnd[pos]) rotate(pos,p);
    }
    
    void del(int &pos,int x) {
        if(!pos) return;
        if(num[pos]==x) {
            if(fx[pos]>1) {
                fx[pos]--;
                sum[pos]--;
                return;
            }
            if(son[pos][0]*son[pos][1]==0) {
                pos=son[pos][0]+son[pos][1];
                return;
            }
            int p=rnd[son[pos][1]]<rnd[son[pos][0]];
            rotate(pos,p);sum[pos]--;
            del(son[pos][!p],x);
        }
        else {
            sum[pos]--;
            del(son[pos][x>num[pos]],x);
        }
    }
    
    int qnum(int pos,int x) {
        if(x>sum[son[pos][0]]&&x<=sum[son[pos][0]]+fx[pos]) return num[pos];
        if(x<=sum[son[pos][0]]) return qnum(son[pos][0],x);
        return qnum(son[pos][1],x-sum[son[pos][0]]-fx[pos]);
    }
    
    int qrank(int pos,int x) {
        if(x==num[pos]) return sum[son[pos][0]]+1;
        if(x<num[pos]) return qrank(son[pos][0],x);
        return sum[son[pos][0]]+fx[pos]+qrank(son[pos][1],x);
    }
    
    void q1(int pos,int x) {
        if(!pos) return;
        if(num[pos]<x) ans=num[pos],q1(son[pos][1],x);
        else q1(son[pos][0],x);
    }
    
    void q2(int pos,int x) {
        if(!pos) return;
        if(num[pos]>x) ans=num[pos],q2(son[pos][0],x);
        else q2(son[pos][1],x);
    }
    int main() {
        srand(1031);
        n=read();
        int op,x;
        for(int i=1;i<=n;++i) {
            op=read();x=read();
            switch(op) {
                case 1:add(root,x);break;
                case 2:del(root,x);break;
                case 3:printf("%d
    ",qrank(root,x));break;
                case 4:printf("%d
    ",qnum(root,x));break;
                case 5:q1(root,x);printf("%d
    ",ans);break;
                case 6:q2(root,x);printf("%d
    ",ans);break;
            }
        }
        return 0;
    }
    

    而非旋treap支持split和merge很是有趣,这次直接照着Achen的板子学,感受到Achen大佬的数据结构多么优秀。

    merge的时候不想用pair然后就乱搞了一搞,调了一阵子,最后强制把代码改成自己的码风。感觉不是很难打。

    普通平衡树版:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+10,base=28;
    int n,root,tot,ans;
    int son[maxn][2],num[maxn],sum[maxn],rnd[maxn];
    
    int aa,ff;char cc;
    int read() {
    	aa=0;ff=1;cc=getchar();
    	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa*ff;
    }
    
    void ud(int pos){sum[pos]=sum[lc]+sum[rc]+1;}
    ll pr(int x,int y) {return ((ll)x<<base)+(ll)y;}//第一个ll要套在里面 
    int fi(ll x){return x>>base;}
    int se(ll x){return x-((ll)fi(x)<<base);}
    
    int merge(int x,int y) {
    	if((ll)x*y==0) return x^y;
    	if(rnd[x]<rnd[y]) return son[x][1]=merge(son[x][1],y),ud(x),x;
    	else return son[y][0]=merge(x,son[y][0]),ud(y),y;
    }
    
    ll split(int pos,int x) {
    	if(!pos) return 0;
    	ll rs;
    	if(sum[lc]>=x) {
    		rs=split(lc,x);
    		lc=se(rs);
    		rs=pr(fi(rs),pos);
    	}
    	else {
    		rs=split(rc,x-sum[lc]-1);
    		rc=fi(rs);
    		rs=pr(pos,se(rs));
    	}
    	return ud(pos),rs;
    }
    
    int qrank(int pos,int x) {
    	if(!pos) return 1;
    	if(num[pos]<x) return sum[lc]+1+qrank(rc,x);
    	return qrank(lc,x);
    }
    
    int qnum(int pos,int x) {
    	if(x==sum[lc]+1) return num[pos];
    	if(x<=sum[lc]) return qnum(lc,x);
    	return qnum(rc,x-sum[lc]-1);
    }
    
    void q1(int pos,int x) {
        if(!pos) return;
        if(num[pos]<x) ans=num[pos],q1(son[pos][1],x);
        else q1(son[pos][0],x);
    }
     
    void q2(int pos,int x) {
        if(!pos) return;
        if(num[pos]>x) ans=num[pos],q2(son[pos][0],x);
        else q2(son[pos][1],x);
    }
    
    void add(int &pos,int x) {
    	int k=qrank(pos,x); ++tot;
    	num[tot]=x;sum[tot]=1;rnd[tot]=rand();
    	ll p=split(pos,k-1);
    	pos=merge(fi(p),tot);
    	pos=merge(pos,se(p));
    }
    
    void del(int &pos,int x) {
    	int k=qrank(pos,x);
    	ll p=split(pos,k-1);
    	ll q=split(se(p),1);
    	pos=merge(fi(p),se(q));
    }
    
    int main() {
    	srand(1031);n=read();
    	int op,x;
    	while(n--) {
    		op=read(); x=read();
    		switch(op) {
    			case 1:add(root,x);break;
    			case 2:del(root,x);break;
    			case 3:printf("%d
    ",qrank(root,x));break;
    			case 4:printf("%d
    ",qnum(root,x));break;
    			case 5:q1(root,x);printf("%d
    ",ans);break;
                case 6:q2(root,x);printf("%d
    ",ans);break;
    		}
    	}
    	return 0;
    }

    文艺平衡树版:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+10,base=28;
    int n,m,root,tot;
    int son[maxn][2],num[maxn],sum[maxn],rnd[maxn],laz[maxn];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    void ud(int pos){sum[pos]=sum[lc]+sum[rc]+1;}
    void pd(int pos){if(!laz[pos])return;swap(lc,rc);laz[lc]^=1;laz[rc]^=1;laz[pos]=0;}
    ll pr(int x,int y) {return ((ll)x<<base)+(ll)y;}
    int fi(ll x){return x>>base;}
    int se(ll x){return x-((ll)fi(x)<<base);}
    
    int bld(int l,int r) {
    	if(l>r) return 0;
    	int mid=(l+r)>>1,pos=++tot;
    	num[pos]=mid;sum[pos]=1;rnd[pos]=rand();
    	lc=bld(l,mid-1);rc=bld(mid+1,r);
    	return ud(pos),pos;
    }
    
    int merge(int x,int y) {
    	if((ll)x*y==0) return x^y; pd(x); pd(y);
    	if(rnd[x]<rnd[y]) return son[x][1]=merge(son[x][1],y),ud(x),x;
    	else return son[y][0]=merge(x,son[y][0]),ud(y),y;
    }
    
    ll split(int pos,int x) {
    	if(!pos) return 0;
    	ll rs; pd(pos);
    	if(sum[lc]>=x) {
    		rs=split(lc,x);
    		lc=se(rs);
    		rs=pr(fi(rs),pos);
    	}
    	else {
    		rs=split(rc,x-sum[lc]-1);
    		rc=fi(rs);
    		rs=pr(pos,se(rs));
    	}
    	return ud(pos),rs;
    }
    
    void rever() {
    	int l=read(),r=read();
    	ll p=split(root,l-1);
    	ll q=split(se(p),r-l+1);
    	laz[fi(q)]^=1;
    	root=merge(fi(p),fi(q));
    	root=merge(root,se(q));
    }
    
    void print_ans(int pos) {
    	if(!pos) return; pd(pos);
    	print_ans(lc);
    	printf("%d ",num[pos]);
    	print_ans(rc);
    }
    
    int main() {
    	srand(1031);
    	n=read(); m=read();
    	root=bld(1,n);
    	while(m--) rever();
    	print_ans(root);
    	return 0;
    }
    

    Achen说我的Splay不是正常人的打法,我也觉得,但是主要原因是我打Splay的时候有打treap的感觉,然后函数都是递归的不优秀。

    特别烦rotate函数感觉贼难受。还需要多多练习才能熟悉啊。

    普通平衡树版:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+10;
    int n,root,tot,ans;
    int sum[maxn],fx[maxn],num[maxn],son[maxn][2],fa[maxn];
    
    int aa,ff;char cc;
    int read() {
    	aa=0;ff=1;cc=getchar();
    	while(cc<'0'||cc>'9') {
    		if(cc=='-') ff=-1;
    		cc=getchar();
    	}
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa*ff;
    }
    
    void ud(int pos){sum[pos]=sum[lc]+sum[rc]+fx[pos];}
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	fa[son[pos][!p]]=x;son[x][p]=son[pos][!p];
    	fa[x]=pos;         son[pos][!p]=x;
    	fa[pos]=y;         son[y][son[y][1]==x]=pos;
    	ud(x);ud(pos);
    	if(root==x) root=pos; fa[root]=fa[0]=0;
    }
    
    void splay(int pos,int &to) {
    	int x,y;
    	for(;pos!=to;rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(x!=to) (son[x][1]==pos ^ son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void add(int &pos,int x,int f) {
    	if(!pos) {
    		pos=++tot;
    		fa[pos]=f;
    		num[pos]=x;
    	}
    	++sum[pos];
    	if(num[pos]==x) {
    		++fx[pos];
    		return;
    	}
    	add(son[pos][x>num[pos]],x,pos);
    } 
    
    void q1(int pos,int x) {
    	if(!pos) return;
    	if(num[pos]<x) ans=pos,q1(rc,x);
    	else q1(lc,x);
    }
    
    void q2(int pos,int x) {
    	if(!pos) return;
    	if(num[pos]>x) ans=pos,q2(lc,x);
    	else q2(rc,x);
    }
    
    int qnum(int pos,int x) {
    	if(x>sum[lc]&&x<=sum[lc]+fx[pos]) return ans=pos,num[pos];
    	if(x<=sum[lc]) return qnum(lc,x);
    	return qnum(rc,x-sum[lc]-fx[pos]);
    }
    
    int qrank(int pos,int x) {
    	if(x==num[pos]) return ans=pos,sum[lc]+1;
    	if(x<num[pos]) return qrank(lc,x);
    	return sum[lc]+fx[pos]+qrank(rc,x);
    }
    
    void del(int x) {
    	int a,b; a=b=qrank(root,x);
    	splay(ans,root); --sum[root];
    	if((--fx[root])!=0) return;
    	if(!son[root][0]) fa[root=son[root][1]]=0;
    	else if(!son[root][1]) fa[root=son[root][0]]=0;
    	else {
    		qnum(root,a-1);a=ans;
    		qnum(root,b);  b=ans;
    		splay(b,root); splay(a,son[b][0]);
    		fa[son[a][1]]=0;
    		son[a][1]=0;
    	}
    }
    
    int main() {
    	 n=read(); int op,x;
        for(int i=1;i<=n;++i) {
            op=read(); x=read(); fa[ans=0]=sum[0]=fx[0]=0;
            switch(op) {
            	case 1:add(root,x,0);break;
                case 2:del(x);break;
                case 3:printf("%d
    ",qrank(root,x));break;
                case 4:printf("%d
    ",qnum(root,x)); break;
                case 5:q1(root,x);printf("%d
    ",num[ans]);break;
                case 6:q2(root,x);printf("%d
    ",num[ans]);break;
            }
            if(op!=2&&ans&&ans<=tot) splay(ans,root);
        }
    	return 0;
    }  

    文艺平衡树版:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+10;
    int n,m,tot,root,ans;
    int sum[maxn],num[maxn],son[maxn][2],fa[maxn],laz[maxn],zz[maxn];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    void ud(int pos) {sum[pos]=sum[lc]+sum[rc]+1;}
    void pd(int pos) {if(!laz[pos])return;swap(lc,rc);laz[lc]^=1;laz[rc]^=1;laz[pos]=0;}
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	fa[son[pos][!p]]=x;son[x][p]=son[pos][!p];
    	fa[x]=pos;         son[pos][!p]=x;
    	fa[pos]=y;         son[y][son[y][1]==x]=pos;
    	ud(x); ud(pos);
    	if(root==x) root=pos;fa[root]=fa[0]=0;
    }
    
    void splay(int pos,int &to) {
    	int x,y,t=0;
    	for(int p=pos;p!=to;p=fa[p]) zz[++t]=p;
    	zz[++t]=to;
    	while(t) pd(zz[t--]);
    	for(;pos!=to;rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(x!=to) (son[x][1]==pos ^ son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    int bld(int l,int r,int f) {
    	if(l>r) return 0;
    	int pos=++tot,mid=(l+r)>>1;
    	num[pos]=mid; sum[pos]=1; fa[pos]=f;
    	lc=bld(l,mid-1,pos); rc=bld(mid+1,r,pos);
    	return ud(pos),pos;
    }
    
    int qnum(int pos,int x) {
    	pd(pos);if(x<1||x>sum[pos]) return ans=-1;
    	if(x==sum[lc]+1) return num[ans=pos];
    	if(x<=sum[lc]) return qnum(lc,x);
    	return qnum(rc,x-sum[lc]-1);
    }
    
    void rever() {
    	int l=read(),r=read(),a,b; ans=0;
    	qnum(root,l-1); a=ans;
    	qnum(root,r+1); b=ans;
    	if(l==1&&r==n) laz[root]^=1;
    	else if(l==1) splay(b,root),laz[son[b][0]]^=1;
    	else if(r==n) splay(a,root),laz[son[a][1]]^=1;
    	else {
    		splay(b,root);
    		splay(a,son[b][0]);
    		laz[son[a][1]]^=1;
    	}
    }
    
    void print_ans(int pos) {
        if(!pos) return; pd(pos);
        print_ans(lc);
        printf("%d ",num[pos]);
        print_ans(rc);
    }
    
    int main() {
    	n=read(); m=read();
    	root=bld(1,n,0);
    	while(m--) rever();
    	print_ans(root);
    	return 0;
    }
    

      

    bzoj1503郁闷的出纳员

    没有什么好说的,就是一个模板题,treap、非旋treap、splay都可以。

    一个技巧:对于所有员工工资上涨下降可以直接改变工资的最低值,但是注意加入一个员工时对员工工资的处理,还有查询第k大输出-1的情况。

    普通treap:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+10;
    int n,slry,now,tot,root,ans,delans;
    char s[23];
    int sum[maxn],num[maxn],fx[maxn],son[maxn][2],rnd[maxn];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    void rotate(int& pos,int p) {
    	int s=son[pos][p];
    	sum[s]=sum[pos];
    	son[pos][p]=son[s][!p];
    	son[s][!p]=pos;
    	sum[pos]=sum[lc]+sum[rc]+fx[pos];
    	pos=s;
    }
    
    void add(int& pos,int x) {
    	if(!pos) {
    		pos=++tot;
    		num[pos]=x;
    		rnd[pos]=rand();
    	}
    	++sum[pos];
    	if(num[pos]==x) {
    		++fx[pos];
    		return;
    	}
    	int p=x>num[pos];
    	add(son[pos][p],x);
    	if(rnd[son[pos][p]]<rnd[pos]) rotate(pos,p); 
    }
    
    void del(int &pos,int x) {
    	if(!pos) return;
    	if(num[pos]==x) {
    		if(fx[pos]>1) {
    			--sum[pos];
    			--fx[pos];
    			return;
    		}
    		if((ll)son[pos][0]*son[pos][1]==0) {
    			pos=son[pos][0]^son[pos][1];
    			return;
    		}
    		int p=rnd[rc] < rnd[lc];
    		rotate(pos,p); --sum[pos];
    		del(son[pos][!p],x);
    	}
    	else {
    		--sum[pos];
    		del(son[pos][x>num[pos]],x);
    	}
    }
    
    int qnum(int pos,int x) {
    	if(x<=0) return -1+now-slry;
    	if(x>sum[lc]&&x<=sum[lc]+fx[pos]) return num[pos];
    	if(x<=sum[lc]) return qnum(lc,x);
    	return qnum(rc,x-sum[lc]-fx[pos]);
    }
    
    int q(int pos) {
    	if(lc) return q(lc);
    	return num[pos];
    }
    
    void getadd(int x) {
    	if(x<slry) return;
    	add(root,x+now-slry);
    }
    
    void getdel(int x) {
    	int num;
    	while(root&&(num=q(root))<x) {
    		++delans;
    		del(root,num);
    	}
    }
    
    int main() {
    	srand(1031);
    	n=read(); now=slry=read();
    	for(int i=1;i<=n;++i) {
    		scanf("%s",s+1);
    		switch(s[1]) {
    			case 'I':getadd(read());break;
    			case 'A':now-=read(); break;
    			case 'S':now+=read();getdel(now);break;
    			case 'F':printf("%d
    ",qnum(root,sum[root]-read()+1)-now+slry);break;
    		}
    	}
    	printf("%d",delans);
    	return 0;
    }
    

    非旋treap:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+10,base=25;
    int n,slry,now,tot,root,ans,delans;
    char s[23];
    int sum[maxn],num[maxn],son[maxn][2],rnd[maxn];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    void ud(int pos) {sum[pos]=sum[lc]+sum[rc]+1;}
    ll pr(int x,int y) {return ((ll)x<<base)+(ll)y;}
    int fi(ll x) {return x>>base;}
    int se(ll x) {return x-((ll)fi(x)<<base);}
    
    int merge(int x,int y) {
    	if((ll)x*y==0) return x^y;
    	if(rnd[x]<rnd[y]) return son[x][1]=merge(son[x][1],y),ud(x),x;
    	return son[y][0]=merge(x,son[y][0]),ud(y),y;
    }
    
    ll split(int pos,int x) {
    	if(!pos) return 0;
    	ll rs;
    	if(sum[lc]>=x) {
    		rs=split(lc,x);
    		lc=se(rs);
    		rs=pr(fi(rs),pos);
    	}
    	else {
    		rs=split(rc,x-sum[lc]-1);
    		rc=fi(rs);
    		rs=pr(pos,se(rs));
    	}
    	return ud(pos),rs;
    }
    
    int qrank(int pos,int x) {
    	if(!pos) return 1;
    	if(num[pos]<x) return sum[lc]+1+qrank(rc,x);
    	return qrank(lc,x);
    }
    
    int qnum(int pos,int x) {
    	if(x<=0) return -1+now-slry;
    	if(x>sum[lc]&&x<=sum[lc]+1) return num[pos];
    	if(x<=sum[lc]) return qnum(lc,x);
    	return qnum(rc,x-sum[lc]-1);
    }
    
    void getadd(int &pos,int x) {
    	if(x<slry) return;
    	x+=now-slry;
        int k=qrank(pos,x); ++tot;
        num[tot]=x;sum[tot]=1;rnd[tot]=rand();
        ll p=split(pos,k-1);
        pos=merge(fi(p),tot);
        pos=merge(pos,se(p));
    }
    
    void getdel(int &pos,int x) {
    	int k=qrank(pos,x);
    	delans+=k-1;
    	if(k==1) return;
    	ll p=split(root,k-1);
    	pos=se(p);
    }
    
    int main() {
    	srand(1031);
    	n=read(); now=slry=read();
    	for(int i=1;i<=n;++i) {
    		scanf("%s",s+1);
    		switch(s[1]) {
    			case 'I':getadd(root,read());break;
    			case 'A':now-=read(); break;
    			case 'S':now+=read();getdel(root,now);break;
    			case 'F':printf("%d
    ",qnum(root,sum[root]-read()+1)-now+slry);break;
    		}
    	}
    	printf("%d",delans);
    	return 0;
    }
    

      

    LCT

    只要会Splay,LCT就很好打,第一次打是12月18日,因为直接是抄的板,所以1A,

    昨天打SAM+LCT的时候发现有点快忘了LCT怎么打,就重新打了LCT,

    然后link那里写成了newroot(y),fa[x]=y,所以死WA

    然后用二分拼接代码法很快找到了bug

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=3e5+10;
    int n,m,tot;
    int fa[maxn],son[maxn][2],zz[maxn],sum[maxn],num[maxn],laz[maxn];
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;ff=1; cc=getchar();
    	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    bool isroot(int pos) {return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;}
    void ud(int pos) {sum[pos]=sum[lc]^sum[rc]^num[pos];}
    void pd(int pos) {
    	if(!laz[pos]) return;
    	laz[pos]=0; swap(lc,rc);
    	if(lc) laz[lc]^=1;
    	if(rc) laz[rc]^=1;
    }
    
    void rotate(int pos) {
    	int x,y,p;y=fa[x=fa[pos]];
    	p=son[x][1]==pos;
    	if(!isroot(x)) son[y][son[y][1]==x]=pos;fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    void splay(int pos) {
    	int x,y,t=0;
    	for(x=pos;!isroot(x);x=fa[x]) zz[++t]=x; zz[++t]=x;
    	while(t) pd(zz[t--]);
    	for(;!isroot(pos);rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(!isroot(x)) 
    			(son[x][1]==pos)^(son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void access(int pos) {
    	for(int t=0;pos;pos=fa[t=pos]) {
    		splay(pos); rc=t; ud(pos);
    	}
    }
    
    int findroot(int pos) {
    	access(pos);
    	splay(pos);
    	while(lc) pos=lc;
    	return pos;
    }
    
    void newroot(int pos) {
    	access(pos);
    	splay(pos);
    	laz[pos]^=1;
    }
    
    void lk(int x,int y) {
    	if(findroot(x)==findroot(y)) return ;
    	newroot(x);
    	fa[x]=y;
    }
    
    void del(int x,int y) {
    	newroot(x);
    	access(y);
    	splay(y);
    	if(son[y][0]==x) fa[x]=son[y][0]=0;
    }
    
    int Yth(int x,int y) {
    	newroot(x);
    	access(y);
    	splay(y);
    	return sum[y];
    }
    
    void mdf(int x,int y) {
    	splay(x);
    	num[x]=y;
    	ud(x);
    }
    
    int main() {
    	read(n); read(m);
    	int op,x,y;
    	for(int i=1;i<=n;++i) read(num[i]);
    	for(int i=1;i<=m;++i) {
    		read(op); read(x); read(y);
    		switch(op) {
    			case 0:printf("%d
    ",Yth(x,y)); break;
    			case 1:lk(x,y); break;
    			case 2:del(x,y); break;
    			case 3:mdf(x,y); break;
    		}
    	}
    	return 0;
    }
    

    可持久化treap

    就是在merge和split的时候新开一下节点就可以了

    克服了心理障碍就没什么难打的

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define lc son[pos][0]
    #define rc son[pos][1]
    const ll maxn=1e6+7,base=25,INF=2147483647;
    int n,tot,root[maxn];
    int num[25*maxn],sum[25*maxn],rnd[25*maxn],son[25*maxn][2];
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
        aa=0;ff=1; cc=getchar();
        while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
        if(cc=='-') ff=-1,cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        aa*=ff;
    }
    
    ll pr(ll x,ll y) {return (x<<base)+y;}
    ll fi(ll x) {return x>>base;}
    ll se(ll x) {return x-(fi(x)<<base);}
    void ud(int pos) {sum[pos]=sum[lc]+sum[rc]+1;}
    
    void copy(int pos,int x) {
        num[pos]=num[x];
        sum[pos]=sum[x];
        rnd[pos]=rnd[x];
        lc=son[x][0]; rc=son[x][1];
    }
    
    bool exit(int pos,int x) {
        while(num[pos]!=x&&pos) {
            if(x<num[pos]) pos=lc;
            else pos=rc;
        }
        return pos;
    }
    
    int merge(int x,int y) {
        if((ll)x*y==0) return x^y;
        int pos=++tot;
        if(rnd[x]<rnd[y]) copy(pos,x),rc=merge(rc,y);
        else copy(pos,y),lc=merge(x,lc);
        return ud(pos),pos;
    }
    
    ll split(int p,int x) {
        if(!p) return 0;
        int pos=++tot; copy(pos,p);
        ll rs;
        if(sum[lc]>=x) {
            rs=split(lc,x);
            lc=se(rs);
            rs=pr(fi(rs),pos);
        }
        else {
            rs=split(rc,x-sum[lc]-1);
            rc=fi(rs);
            rs=pr(pos,se(rs));
        }
        return ud(pos),rs;
    }
    
    int qrank(int pos,int x) {
        if(!pos) return 1;
        if(num[pos]<x) return sum[lc]+1+qrank(rc,x);
        return qrank(lc,x);
    }
    
    int qnum(int pos,int x) {
        if(x==sum[lc]+1) return num[pos];
        if(x<=sum[lc]) return qnum(lc,x);
        return qnum(rc,x-sum[lc]-1);
    }
    
    void add(int &pos,int x) {
        int k=qrank(pos,x);
        ll p=split(pos,k-1);
        num[++tot]=x;sum[tot]=1;rnd[tot]=rand();
        pos=merge(fi(p),tot);
        pos=merge(pos,se(p));
    }
    
    void del(int &pos,int x) {
        if(!exit(pos,x)) return;
        int k=qrank(pos,x);
        ll p=split(pos,k-1);
        ll q=split(se(p),1);
        pos=merge(fi(p),se(q));
    }
    
    int q1(int pos,int x) {
        if(!pos) return -INF;
        if(num[pos]<x) return max(q1(rc,x),num[pos]);
        else return q1(lc,x);
    }
    
    int q2(int pos,int x) {
        if(!pos) return INF;
        if(num[pos]>x) return min(q2(lc,x),num[pos]);
        else return q2(rc,x);
    }
    
    int main() {
        srand(1031);
        read(n);int op,x,p;
        for(int i=1;i<=n;++i) {
            read(p); read(op); read(x);
            root[i]=root[p];
            switch(op) {
                case 1:add(root[i],x);break;
                case 2:del(root[i],x); break;
                case 3:printf("%d
    ",qrank(root[i],x));break;
                case 4:printf("%d
    ",qnum(root[i],x));break;
                case 5:printf("%d
    ",q1(root[i],x));break;
                case 6:printf("%d
    ",q2(root[i],x));break;
            }
            if(!root[i]) root[i]=merge(son[root[i]][0],son[root[i]][1]);
        }
        return 0;
    }
    /*
    10
    0 1 9
    1 1 3
    1 1 10
    2 4 2
    3 3 9
    3 1 2
    6 4 1
    6 2 9
    8 6 3
    4 5 8
    */ 
    

    树上莫队(uoj58糖果公园)

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    const int maxn=1e5+7,maxs=21;
    int n,m,q,size;
    ll nowans,v[maxn],w[maxn],c[maxn],ans[maxn];
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;ff=1; cc=getchar();
    	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int dep[maxn],fa[maxn][maxs],dfn[maxn],dfsclock;
    int bel[maxn],totb;
    int zz[maxn],top;
    
    struct Ask{
    	int x,y,id,t;
    	Ask(){}
    	Ask(int x,int y,int id,int t):x(x),y(y),id(id),t(t){}
    }ask[maxn];
    int totask;
    bool cmp(const Ask& a,const Ask& b) {
    	return bel[a.x]==bel[b.x]? 
    			(bel[a.y]==bel[b.y]? a.t<b.t:bel[a.y]<bel[b.y])
    		:	bel[a.x]<bel[b.x];
    }
    
    struct Mdf{
    	int pos,now,last;
    	Mdf(){}
    	Mdf(int pos,int now,int last):pos(pos),now(now),last(last){	}
    }mdf[maxn];
    int totmdf;
    
    int fir[maxn],nxt[2*maxn],to[2*maxn],e=0;
    void add(int x,int y) {
    	to[++e]=y;nxt[e]=fir[x];fir[x]=e;
    	to[++e]=x;nxt[e]=fir[y];fir[y]=e;
    }
    
    void together(int l,int &r) {
    	++totb;  while(r>l) bel[zz[r--]]=totb;
    }
    
    void dfs(int pos,int d) {
    	int bot=top,y,z;
    	dfn[pos]=++dfsclock;
    	dep[pos]=d;
    	for(int i=1;i<20;++i) fa[pos][i]=fa[fa[pos][i-1]][i-1];
    	for(y=fir[pos];y;y=nxt[y]) {
    		if((z=to[y])==fa[pos][0]) continue;
    		fa[z][0]=pos; dfs(z,d+1);
    		if(top-bot>=size) together(bot,top);
    	}
    	zz[++top]=pos;
    }
    
    int get_lca(int x,int y) {
    	if(dep[x]!=dep[y]) {
    		if(dep[x]<dep[y]) swap(x,y);
    		for(int i=19;(~i)&&dep[x]>dep[y];--i) 
    			if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    	}
    	if(x==y) return x;
    	for(int i=19;~i;--i) if(fa[x][i]!=fa[y][i]) {
    		x=fa[x][i];y=fa[y][i];
    	}
    	return fa[x][0];
    }
    
    bool vis[maxn];int sum[maxn];
    void chge(int pos,int p) {
    	if(p) {
    		sum[c[pos]]++;
    		nowans+=(ll)w[sum[c[pos]]]*v[c[pos]];
    	}
    	else {
    		nowans-=(ll)w[sum[c[pos]]]*v[c[pos]];
    		sum[c[pos]]--;
    	}
    }
    
    void fz(int x,int y) {
    	int lca=get_lca(x,y);
    	for(int i=x;i!=lca;i=fa[i][0]) chge(i,vis[i]^=1);
    	for(int i=y;i!=lca;i=fa[i][0]) chge(i,vis[i]^=1);
    }
    
    int main() {
    	read(n); read(m); read(q);
    	size=0.5*pow(n,2.0/3);
    	int op,x,y;
    	for(int i=1;i<=m;++i) read(v[i]);
    	for(int i=1;i<=n;++i) read(w[i]);
    	for(int i=1;i<n;++i) {
    		read(x); read(y);
    		add(x,y);
    	}
    	dfs(1,1);
    	while(top) bel[zz[top--]]=totb;
    	for(int i=1;i<=n;++i) read(c[i]);
    	for(int i=1;i<=q;++i) {
    		read(op); read(x); read(y);
    		if(!op) {mdf[++totmdf]=Mdf(x,y,c[x]);c[x]=y;}
    		else {
    			if(dfn[x]>dfn[y]) swap(x,y);
    			++totask;
    			ask[totask]=Ask(x,y,totask,totmdf);
    		}
    	}
    	for(int i=totmdf;i;--i) c[mdf[i].pos]=mdf[i].last;
    	
    	sort(ask+1,ask+totask+1,cmp); 
    	int nowt=0,pos,lastx=ask[1].x,lasty=ask[1].y;
    	fz(lastx,lasty);
    	for(int i=1;i<=totask;++i) {
    		x=ask[i].x; y=ask[i].y;
    		while(nowt>ask[i].t) {
    			pos=mdf[nowt].pos;
    			if(vis[pos]) chge(pos,0);
    			c[pos]=mdf[nowt--].last;
    			if(vis[pos]) chge(pos,1);
    		}
    		while(nowt<ask[i].t) {
    			pos=mdf[++nowt].pos;
    			if(vis[pos]) chge(pos,0);
    			c[pos]=mdf[nowt].now;
    			if(vis[pos]) chge(pos,1);
    		}
    		fz(lastx,x); fz(lasty,y);
    		pos=get_lca(x,y);
    		chge(pos,vis[pos]^=1);
    		ans[ask[i].id]=nowans;
    		chge(pos,vis[pos]^=1);
    		lastx=x; lasty=y;
    	}
    	for(int i=1;i<=totask;++i) 	printf("%lld
    ",ans[i]);
    	return 0;
    }
    /*
    4 3 5
    1 9 2
    7 6 5 1
    2 3
    3 1
    3 4
    1 2 3 2
    1 1 2
    1 4 2
    0 2 1
    1 1 2
    1 4 2
    */
    

    一些Achen几万年前就A过的模板题:

    bzoj1208宠物收养所

    treap/splay随便维护一下即可

    注意bz上交不能有srand,为此debug2h

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+7;
    const ll mod=1000000;
    int n,root,now=-1,tot; ll ans,INF=1e14;
    int son[maxn][2],rnd[maxn];ll num[maxn];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    void rotate(int &pos,int p) {
    	int s=son[pos][p];
    	son[pos][p]=son[s][!p];
    	son[s][!p]=pos;
    	pos=s;
    }
    
    void add(int &pos,ll x) {
    	if(!pos) {
    		pos=++tot;
    		num[pos]=x;
    		rnd[pos]=rand()*rand();
    		return;
    	}
    	int p=x>num[pos];
    	add(son[pos][p],x);
    	if(rnd[son[pos][p]]<rnd[pos]) rotate(pos,p);
    }
    
    void del(int &pos,ll x) {
    	if(!pos) return;
    	if(num[pos]==x) {
    		if((ll)lc*rc==0) {
    			pos=lc^rc;
    			return;
    		}
    		int p=rnd[rc]<rnd[lc];
    		rotate(pos,p);
    		del(son[pos][!p],x);
    	}
    	else del(son[pos][x>num[pos]],x);
    }
    
    ll q1(int pos,ll x) {
    	if(!pos) return -INF;
    	if(num[pos]<=x) return max(q1(rc,x),num[pos]);
    	return q1(lc,x);
    }
    
    ll q2(int pos,ll x) {
    	if(!pos) return INF;
    	if(num[pos]>=x) return min(q2(lc,x),num[pos]);
    	return q2(rc,x);
    }
    
    int main() {
    	read(n); ll x,y,p1,p2;
    	For(i,1,n) {
    		read(x); read(y);
    		if(x==now||(!root)) {
    			add(root,y); now=x;
    		}
    		else {
    			p1=q1(root,y); p2=q2(root,y);
    			if(y-p1<=p2-y) del(root,p1),ans+=(y-p1);
    			else del(root,p2),ans+=(p2-y);
    			ans%=mod;
    		}
    	}
    	printf("%lld",ans);
    	return 0;
    }
    

    bzoj2733永无乡

    splay+启发式合并

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+7;
    int n,m;
    char s[maxn];
    int num[maxn],sum[maxn],fa[maxn],son[maxn][2];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int f[maxn];
    int find(int x){return x==f[x]? x:f[x]=find(f[x]);}
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p= son[x][1]==pos;
    	fa[son[pos][!p]]=x; son[x][p]=son[pos][!p];
    	fa[x]=pos; son[pos][!p]=x;
    	fa[pos]=y; son[y][son[y][1]==x]=pos;
    	sum[pos]=sum[x];
    	sum[x]=sum[son[x][0]]+sum[son[x][1]]+1;
    } 
    
    void add(int &pos,int x,int f) {
    	if(!pos) {
    		pos=x;
    		fa[pos]=f;
    		return;
    	}
    	sum[pos]+=sum[x];
    	add(son[pos][num[x]>num[pos]],x,pos);
    }
    
    void splay(int pos) {
    	int x,y;
    	for(;fa[pos];rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(y) (son[x][1]==pos ^ son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void insert(int root,int pos) {
    	if(!pos) return;
    	int lson=lc,rson=rc;
    	fa[lc]=fa[rc]=0; lc=rc=0;
    	sum[pos]=1; add(root,pos,0);
    	insert(root,lson); insert(root,rson);
    }
    
    void lik(int x,int y) {
    	if(find(x)==find(y)) return;
    	f[find(x)]=find(y);
    	splay(x);splay(y);
    	if(sum[x]<sum[y]) swap(x,y);
    	insert(x,y);
    }
    
    int qnum(int pos,int x) {
    	if(x==sum[lc]+1) return pos;
    	if(x<=sum[lc]) return qnum(lc,x);
    	return qnum(rc,x-sum[lc]-1);
    }
    
    int q(int pos,int x) {
    	splay(pos);
    	if(x>sum[pos]) return -1;
    	return qnum(pos,x);
    }
    
    int main() {
    	read(n); read(m);
    	int x,y;
    	For(i,1,n) f[i]=i,read(num[i]=i),sum[i]=1;
    	For(i,1,m) {
    		read(x); read(y);
    		lik(x,y);
    	}
    	read(m);
    	For(i,1,m) {
    		scanf("%s",s+1); read(x); read(y);
    		if(s[1]=='B') lik(x,y);
    		else printf("%d
    ",q(x,y));
    	}
    	return 0;
    }
    /*
    5 1           
    4 3 2 5 1
    1 2
    7
    Q 3 2
    Q 2 1
    B 2 3
    B 1 5
    Q 2 1
    Q 2 4
    Q 2 3
    */
    

    bzoj2843极地旅行社

    LCT

    一开始1e5+7打+的时候按成了Backspace,结果打成1e7然后MLE了

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+7;
    int n,m,f[maxn]; char s[maxn];
    int fa[maxn],sum[maxn],son[maxn][2],num[maxn],laz[maxn];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int find(int x){return x==f[x]? x:f[x]=find(f[x]);}
    
    bool isroot(int pos){return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;}
    void ud(int pos) {sum[pos]=sum[lc]+sum[rc]+num[pos];}
    void pd(int pos) {
    	if(!laz[pos]) return;
    	swap(lc,rc); laz[pos]=0;
    	if(lc) laz[lc]^=1;
    	if(rc) laz[rc]^=1;
    }
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(!isroot(x)) son[y][son[y][1]==x]=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[x][p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    int zz[maxn];
    void splay(int pos) {
    	int x,y,t=0;
    	for(x=pos;!isroot(x);x=fa[x]) zz[++t]=x; zz[++t]=x;
    	while(t) pd(zz[t--]);
    	for(;!isroot(pos);rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(!isroot(x)) (son[x][1]==pos ^ son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void access(int pos) {
    	for(int t=0;pos;pos=fa[t=pos]) {
    		splay(pos); rc=t; ud(pos);
    	}
    }
    
    void newroot(int pos) {
    	access(pos);
    	splay(pos);
    	laz[pos]^=1;
    }
    
    void lik(int x,int y) {
    	if(find(x)==find(y)) {
    		printf("no
    "); return;
    	}
    	printf("yes
    ");
    	newroot(x); fa[x]=y; f[find(x)]=find(y);
    }
    
    void chge(int pos,int y) {
    	splay(pos); 
    	num[pos]=y; 
    	ud(pos);
    }
    
    int q(int x,int y) {
    	if(find(x)!=find(y)) return -1;
    	newroot(x); access(y); splay(y);
    	return sum[y];
    }
    
    int main() {
    	read(n); int x,y,ans;
    	For(i,1,n) read(num[i]),f[i]=i;
    	read(m); 
    	For(i,1,m) {
    		scanf("%s",s+1); read(x); read(y);
    		if(s[1]=='b') lik(x,y);
    		else if(s[1]=='p') chge(x,y);
    		else {
    			ans=q(x,y);
    			if(ans==-1) printf("impossible
    ");
    			else printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    /*
    5
    4 2 4 5 6
    10
    excursion 1 1
    excursion 1 2
    bridge 1 2
    excursion 1 2
    bridge 3 4
    bridge 3 5
    excursion 4 5
    bridge 1 3
    excursion 2 4
    excursion 2 5
    */

    bzoj2002 弹飞绵羊

    LCT:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=2e5+7;
    int n,m,sum[maxn],fa[maxn],son[maxn][2];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    void ud(int pos) {sum[pos]=sum[lc]+sum[rc]+1;}
    bool isroot(int pos){return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;}
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(!isroot(x)) son[y][son[y][1]==x]=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    void splay(int pos) {
    	int x,y;
    	for(;!isroot(pos);rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(!isroot(x)) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void access(int pos) {
    	for(int t=0;pos;pos=fa[t=pos]) {
    		splay(pos);
    		rc=t;
    		ud(pos);
    	}
    }
    
    void cut(int x) {
    	access(x); splay(x);
    	fa[son[x][0]]=0; son[x][0]=0;
    	ud(x);
    }
    
    int main() {
    	read(n); int op,x,y;
    	For(i,1,n+1) sum[i]=1;
    	For(i,1,n) {
    		read(x);
    		fa[i]=min(i+x,n+1);
    	}
    	read(m);
    	For(i,1,m) {
    		read(op); read(x); x++;
    		if(op==1) {
    			access(x); 
    			splay(x);
    			printf("%d
    ",sum[son[x][0]]);
    		}
    		else {
    			read(y);
    			y=min(y+x,n+1);
    			cut(x); 
    			fa[x]=y;
    		}
    	}
    	return 0;
    }
    

    Splay维护括号序列:

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=4e5+7;
    int n,m,root,num[maxn],sum[maxn],fa[maxn],son[maxn][2];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int fir[maxn],nxt[maxn],to[maxn],e=0;
    void add(int x,int y) {
    	to[++e]=y;nxt[e]=fir[x];fir[x]=e;
    }
    
    int dfn[maxn],end[maxn],dfn_clock;
    void dfs(int pos) {
    	num[dfn[pos]=++dfn_clock]=1;
    	for(int y=fir[pos];y;y=nxt[y]) dfs(to[y]);
    	num[end[pos]=++dfn_clock]=-1;
    }
    
    void ud(int pos) {sum[pos]=num[pos]+sum[lc]+sum[rc];}
    
    void bld(int &pos,int l,int r,int f) {
    	if(l>r) {pos=0;return;}
    	pos=(l+r)>>1; fa[pos]=f;
    	bld(lc,l,pos-1,pos);
    	bld(rc,pos+1,r,pos);
    	ud(pos);
    }
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(y) son[y][son[y][1]==x]=pos; else root=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    void splay(int pos) {
    	int x,y;
    	for(;fa[pos];rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(y) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    int split(int pos) {
    	splay(pos); int rs;
    	fa[rs=rc]=0; rc=0;
    	ud(pos); 
    	return rs;
    }
    
    void merge(int x,int y) {
    	splay(x); splay(y);
    	while(son[x][1]) x=son[x][1];
    	splay(x); fa[y]=x; son[x][1]=y;
    	ud(x);
    }
    
    int q(int pos) {
    	splay(pos);
    	pos=lc;
    	while(rc) pos=rc;
    	return pos;
    }
    
    int main() {
    	read(n); int op,x,y,l,r;
    	For(i,1,n) {
    		read(x);
    		x=min(i+x,n+1);
    		add(x,i);
    	}
    	dfs(n+1);
    	bld(root,1,dfn_clock,0);
    	
    	son[2*n+3][0]=root; fa[root]=2*n+3;
    	ud(2*n+3); root=2*n+3;
    	son[2*n+4][1]=root; fa[root]=2*n+4;
    	ud(2*n+4); root=2*n+4;
    	
    	read(m);
    	For(i,1,m) {
    		read(op); read(x); ++x;
    		if(op==1) {
    			splay(x=dfn[x]);
    			printf("%d
    ",sum[son[x][0]]);
    		}
    		else {
    			read(y); y=min(y+x,n+1);
    			l=q(dfn[x]);
    			split(l);
    			r=split(end[x]);
    			merge(l,r);
    			split(dfn[y]);
    			merge(dfn[y],end[x]);
    			merge(end[x],end[y]);
    		}
    	}
    	return 0;
    }

    bzoj3786 星系探索

    splay维护括号序列(下面是一份还T着的代码)

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=2e5+7;
    int n,m,root;
    char s[13];
    ll w[maxn],d[maxn],tot[maxn],sum[maxn],num[maxn],laz[maxn];
    int son[maxn][2],fa[maxn];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int fir[maxn],nxt[maxn],to[maxn],e=0;
    void add(int x,int y) {
    	to[++e]=y;nxt[e]=fir[x];fir[x]=e;
    }
    
    int dfn[maxn],end[maxn],dfn_clock;
    void dfs(int pos) {
    	num[dfn[pos]=++dfn_clock]=w[pos]; d[dfn_clock]=1;
    	for(int y=fir[pos];y;y=nxt[y]) dfs(to[y]);
    	num[end[pos]=++dfn_clock]=-w[pos]; d[dfn_clock]=-1;
    }
    
    void ud(int pos) {sum[pos]=num[pos]+sum[lc]+sum[rc];tot[pos]=d[pos]+tot[lc]+tot[rc];}
    void add_tag(int pos,ll x) {
    	sum[pos]+=tot[pos]*x;
    	num[pos]+=d[pos]*x;//
    	laz[pos]+=x;
    }
    void pd(int pos) {
    	if(!laz[pos]) return;
    	if(lc) add_tag(lc,laz[pos]);
    	if(rc) add_tag(rc,laz[pos]);
    	laz[pos]=0;
    }
    
    void bld(int &pos,int l,int r,int f) {
    	if(l>r) {pos=0;return;}
    	pos=(l+r)>>1; fa[pos]=f;
    	bld(lc,l,pos-1,pos);
    	bld(rc,pos+1,r,pos);
    	ud(pos);
    }
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(y) son[y][son[y][1]==x]=pos; else root=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    int zz[maxn];
    void splay(int pos) {
    	int t=0,x,y;
    	for(int p=pos;p;p=fa[p]) zz[++t]=p;
    	while(t) pd(zz[t--]);
    	for(;fa[pos];rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(y) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    int split(int pos) {
    	splay(pos); int rs;
    	fa[rs=rc]=0; rc=0;
    	ud(pos); return rs;
    }
    
    void merge(int x,int y) {
    	splay(x); splay(y);//
    	while(son[x][1]) pd(x),x=son[x][1];
    	splay(x); fa[y]=x; son[x][1]=y;
    	ud(x);
    }
    
    int q(int pos) {
    	splay(pos); pos=lc;
    	while(rc) pd(pos),pos=rc;
    	return pos;
    }
    
    int main() {
    	read(n); ll x,y,l,r;
    	For(i,2,n) {
    		read(x);
    		add(x,i);
    	}
    	For(i,1,n) read(w[i]);
    	dfs(1);
    	bld(root,1,dfn_clock,0);
    	
    	son[2*n+3][0]=root; fa[root]=2*n+3;
    	ud(2*n+3); root=2*n+3;
    	son[2*n+4][1]=root; fa[root]=2*n+4;
    	ud(2*n+4); root=2*n+4;
    	
    	read(m);
    	For(i,1,m) {
    		scanf("%s",s+1); read(x);
    		if(s[1]=='Q') {
    			splay(x=dfn[x]);
    			printf("%lld
    ",sum[son[x][0]]+num[x]);
    		}
    		else if(s[1]=='C') {
    			read(y);
    			l=q(dfn[x]);
    			split(l);
    			r=split(end[x]);
    			split(dfn[y]);
    			merge(dfn[y],dfn[x]);
    			merge(dfn[x],end[y]);
    		}
    		else {
    			read(y);
    			l=q(dfn[x]);
    			split(l);
    			r=split(end[x]);
    			splay(dfn[x]);
    			add_tag(dfn[x],y);
    			merge(l,dfn[x]);
    			merge(dfn[x],r);
    		}
    	}
    	return 0;
    }
    /*
    3
    1
    1
    4 5 7
    5
    Q 2
    F 1 3
    Q 2
    C 2 3
    Q 2
    */

    bzoj4530 大融合

    LCT维护子树信息,又把rotate的p和!p写错了,debug真烦

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=1e5+7;
    int n,m,fa[maxn],sum[maxn],tot[maxn],son[maxn][2],laz[maxn];
    char s[13];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    bool isroot(int pos) {return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;}
    void ud(int pos){sum[pos]=sum[lc]+sum[rc]+tot[pos]+1;}
    void pd(int pos) {
    	if(!laz[pos]) return;
    	swap(lc,rc);
    	laz[lc]^=1;
    	laz[rc]^=1;
    	laz[pos]=0;
    }
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(!isroot(x)) son[y][son[y][1]==x]=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    int zz[maxn];
    void splay(int pos) {
    	int x,y,p,t=0;
    	for(p=pos;!isroot(p);p=fa[p]) zz[++t]=p;
    	zz[++t]=p;
    	while(t) pd(zz[t--]);
    	for(;!isroot(pos);rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(!isroot(x)) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void access(int pos) {
    	for(int t=0;pos;pos=fa[t=pos]) {
    		splay(pos);
    		tot[pos]+=sum[rc]-sum[t];
    		rc=t; ud(pos);
    	}
    }
    
    void newroot(int pos) {
    	access(pos);
    	splay(pos);
    	laz[pos]^=1;
    }
    
    void lk(int x,int y) {
    	newroot(x); newroot(y);
    	fa[y]=x; tot[x]+=sum[y];
    	ud(x);
    }
    
    int main() {
    	read(n); read(m); int x,y;
    	For(i,1,n) sum[i]=1;
    	For(i,1,m) {
    		scanf("%s",s+1);
    		read(x); read(y);
    		if(s[1]=='A') lk(x,y);
    		else {
    			newroot(x); newroot(y);
    			printf("%lld
    ",(ll)(sum[y]-sum[x])*sum[x]);
    		}
    	}
    	return 0;
    }
    

    UOJ207 共价大爷游长沙

    LCT维护子树信息

    num和sum没分清

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=3e5+7;
    int n,m,son[maxn][2],fa[maxn],laz[maxn];
    ll now,sum[maxn],num[maxn];
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    struct Node{
    	int x,y;ll num;
    	Node(){}
    	Node(int x,int y,ll num):x(x),y(y),num(num){}
    }node[maxn];
    int tot;
    
    bool isroot(int pos){return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;}
    void ud(int pos){sum[pos]=sum[lc]^sum[rc]^num[pos];}
    void pd(int pos) {
    	if(!laz[pos]) return;
    	swap(lc,rc);
    	if(lc) laz[lc]^=1;
    	if(rc) laz[rc]^=1;
    	laz[pos]=0;
    }
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(!isroot(x)) son[y][son[y][1]==x]=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    int zz[maxn];
    void splay(int pos) {
    	int x,y,p,t=0;
    	for(p=pos;!isroot(p);p=fa[p]) zz[++t]=p;
    	zz[++t]=p;
    	while(t) pd(zz[t--]);
    	for(;!isroot(pos);rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(!isroot(x)) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void access(int pos) {
    	for(int t=0;pos;pos=fa[t=pos]) {
    		splay(pos);
    		num[pos]^=(sum[rc]^sum[t]);//
    		rc=t;
    		ud(pos);
    	}
    }
    
    void newroot(int pos) {
    	access(pos);
    	splay(pos);
    	laz[pos]^=1;
    }
    
    void lk(int x,int y) {
    	newroot(x); newroot(y);//
    	fa[y]=x; num[x]^=sum[y];
    	ud(x);
    }
    
    void del(int x,int y) {
    	newroot(x); access(y); splay(y);
    	son[y][0]=fa[x]=0;
    	ud(y);
    }
    
    int main() {
    	srand(1031);
    	read(n); int op,x,y; ll r;
    	read(n); read(m);
    	For(i,1,n-1) {
    		read(x); read(y);
    		lk(x,y);
    	}
    	For(i,1,m) {
    		read(op);
    		if(op==1) {
    			read(x); read(y);
    			del(x,y);
    			read(x); read(y);
    			lk(x,y);
    		}
    		else if(op==2) {
    			read(x); read(y);
    			node[++tot]=Node(x,y,r=rand()*rand());
    			newroot(x); num[x]^=r; ud(x);
    			newroot(y); num[y]^=r; ud(y);
    			now^=r;
    		}
    		else if(op==3) {
    			read(r);
    			x=node[r].x; y=node[r].y;
    			r=node[r].num;
    			newroot(x); num[x]^=r; ud(x);
    			newroot(y); num[y]^=r; ud(y);
    			now^=r;
    		}
    		else {
    			read(x); read(y);
    			newroot(x); newroot(y);
    			printf(sum[x]==now?"YES
    ":"NO
    ");
    		}
    	}
    	return 0;
    }
    /*
    0
    5 7
    1 2
    1 3
    2 4
    1 5
    2 1 5
    1 1 5 2 5
    4 2 5
    2 1 4
    4 2 5
    3 1
    4 2 4
    */
    

    bzoj4573大森林

    感觉是一道非常有意思的题

    当时看到这道题也觉得这种题肯定是把所有树的共同点一起维护了,然后对于不同的树的查询修改些地方

    对于每次换生长节点就建一个虚点(权为0)

    然后生长就在上一个建的虚点上长实点(权为1)

    先把虚点串起来,考虑离线后,按照区间从左到右做

    一个虚点会在一段时间有用,就把他连到对于实点的下面

    否则他的父亲就是上一个虚点。

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=3e5+7;
    int n,m,ans[maxn];
    int son[maxn][2],fa[maxn],sum[maxn],num[maxn];
    int L[maxn],R[maxn],id[maxn],tid,tot,last;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    struct Ask{
    	int pos,t,x,y;
    	Ask(){}
    	Ask(int pos,int t,int x,int y):pos(pos),t(t),x(x),y(y){}
    	bool operator < (const Ask& b) const{return pos==b.pos? t<b.t:pos<b.pos;}
    }ask[2*maxn];
    int totask,totq;
    
    void ud(int pos){sum[pos]=sum[lc]+sum[rc]+num[pos];}
    int newnode(int x) {num[++tot]=x; ud(tot); return tot;}
    bool isroot(int pos) {return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;}
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(!isroot(x)) son[y][son[y][1]==x]=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    void splay(int pos) {
    	for(int x,y;!isroot(pos);rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(!isroot(x)) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    int access(int pos) {
    	int t=0;
    	for(;pos;pos=fa[t=pos]) {
    		splay(pos);
    		rc=t;
    		ud(pos);
    	}
    	return t;
    }
    
    void lk(int x,int y) {
    	splay(x);
    	fa[x]=y;
    }
    
    void cut(int pos) {
    	access(pos);
    	splay(pos);
    	fa[lc]=0; lc=0;
    	ud(pos);
    }
    
    int Yth(int x,int y) {
    	int rs=0,lca;
    	access(x); splay(x); rs+=sum[x];
    	lca=access(y); splay(y); rs+=sum[y];
    	access(lca); splay(lca); rs-=2*sum[lca];
    	return rs;
    }
    
    int main() {
    	read(n); read(m);
    	id[++tid]=newnode(1);L[1]=1;R[1]=n;
    	newnode(0);lk(2,1);last=2;
    	int op,l,r,x;
    	For(i,1,m) {
    		read(op);
    		if(op==0) {
    			read(l); read(r);
    			id[++tid]=newnode(1);
    			L[tot]=l; R[tot]=r;
    			lk(tot,last);
    		}
    		else if(op==1) {
    			read(l); read(r); read(x);
    			l=max(l,L[id[x]]); r=min(r,R[id[x]]);
    			if(l>r) continue;
    			lk(newnode(0),last);
    			ask[++totask]=Ask(l,i-m,tot,id[x]);
    			ask[++totask]=Ask(r+1,i-m,tot,last);
    			last=tot;
    		}
    		else {
    			read(x); read(l); read(r);
    			ask[++totask]=Ask(x,++totq,id[l],id[r]);
    		}
    	}
    	sort(ask+1,ask+totask+1);
    	For(i,1,totask) {
    		if(ask[i].t<=0) {
    			cut(ask[i].x);
    			lk(ask[i].x,ask[i].y);
    		}
    		else ans[ask[i].t]=Yth(ask[i].x,ask[i].y);
    	}
    	For(i,1,totq) printf("%d
    ",ans[i]);
    	return 0;
    }
    /*
    5 5
    0 1 5
    1 2 4 2
    0 1 4
    2 1 1 3
    2 2 1 3
    */
    

    bzoj3669魔法森林

    没有删除操作的动态MST问题

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=2e5+7,INF=0x3f3f3f3f;
    int n,m,f[maxn],ans=INF;
    int num[maxn],maxnum[maxn],son[maxn][2],fa[maxn],laz[maxn],tot;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    int find(int x) {return x==f[x]? x:f[x]=find(f[x]);}
    
    struct Node{
    	int x,y,a,b;
    	bool operator < (const Node& r) const{return a==r.a? b<r.b:a<r.a;}
    }node[maxn];
    
    void ud(int pos){
    	maxnum[pos]=num[maxnum[lc]]>num[maxnum[rc]]? maxnum[lc]:maxnum[rc];
    	if(num[pos]>num[maxnum[pos]]) maxnum[pos]=pos;
    }
    bool isroot(int pos) {return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;}
    int newnode(int r) {num[++tot]=r; ud(tot); return tot;}
    void pd(int pos) {
    	if(!laz[pos]) return ;
    	swap(lc,rc);
    	if(lc) laz[lc]^=1;
    	if(rc) laz[rc]^=1;
    	laz[pos]=0;
    }
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(!isroot(x)) son[y][son[y][1]==x]=pos; fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    int zz[maxn];
    void splay(int pos) {
    	int x,y,t=0,p;
    	for(p=pos;!isroot(p);p=fa[p]) zz[++t]=p; zz[++t]=p;
    	while(t) pd(zz[t--]);
    	for(;!isroot(pos);rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(!isroot(x)) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    void access(int pos) {
    	for(int t=0;pos;pos=fa[t=pos]) {
    		splay(pos);
    		rc=t;
    		ud(pos);
    	}
    }
    
    void newroot(int pos) {
    	access(pos);
    	splay(pos);
    	laz[pos]^=1;
    }
    
    void lk(int x,int y,int r) {
    	int p=newnode(r);
    	newroot(x); newroot(y);
    	fa[x]=fa[y]=p;
    }
    
    void cut(int pos) {
    	newroot(pos);
    	splay(pos);
    	fa[lc]=fa[rc]=0;
    }
    
    int Yth(int x,int y) {
    	if(find(x)!=find(y)) return -1;
    	newroot(x); 
    	access(y); splay(y);
    	return maxnum[y];
    }
    
    int main() {
    	read(n); read(m);
    	For(i,1,n) newnode(0),f[i]=i;
    	For(i,1,m) {
    		read(node[i].x);
    		read(node[i].y);
    		read(node[i].a);
    		read(node[i].b);
    	}
    	sort(node+1,node+m+1);
    	int x,y,pos;
    	For(i,1,m) {
    		x=node[i].x;
    		y=node[i].y;
    		if(find(x)!=find(y)) {
    			f[find(x)]=find(y);
    			lk(x,y,node[i].b);
    		}
    		else {
    			pos=Yth(x,y);
    			if(num[pos]>node[i].b) {
    				cut(pos);
    				lk(x,y,node[i].b);
    			}
    		}
    		pos=Yth(1,n);
    		if(~pos) ans=min(ans,num[pos]+node[i].a);
    	}
    	if(ans!=INF) printf("%d",ans);
    	else printf("-1");
    	return 0;
    }
    /*
    4 5
    1 2 19 1
    2 3 8 12
    2 4 12 15
    1 3 17 8
    3 4 1 17
    */
    

    bzoj3595方伯伯的OJ

    只要不卡常,什么都好,map+set+splay

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #include<set>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    #define lc son[pos][0]
    #define rc son[pos][1]
    const int maxn=6e5+7;
    const ll Bs=1e7;
    int n,m,tot,root;
    int L[maxn],R[maxn],sum[maxn],num[maxn],fa[maxn],son[maxn][2];
    map<int,int> G,H;
    
    struct Node{
    	int l,r,id;
    	Node(int l,int r,int id):l(l),r(r),id(id){}
    	bool operator < (const Node& b) const{return l==b.l? r<b.r : l<b.l;}
    };
    
    set<Node> P;
    set<Node>::iterator it;
    
    char cc; ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;cc=getchar();ff=1;
    	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    ll pr(ll x,ll y) {return x*Bs+y;}
    ll fi(ll x){return x/Bs;}
    ll se(ll x){return x%Bs;}
    
    void ud(int pos) {num[pos]=R[pos]-L[pos]+1; sum[pos]=num[pos]+sum[lc]+sum[rc];}
    int newnode(int l,int r,int f) {
    	fa[++tot]=f;
    	L[tot]=l; R[tot]=r;
    	P.insert(Node(l,r,tot));
    	ud(tot); 
    	if(f) ud(f);
    	return tot;
    }
    void del(int pos) {
    	Node o=Node(L[pos],R[pos],pos);
    	it=P.lower_bound(o);
    	P.erase(it);
    	lc=rc=fa[pos]=0;
    	num[pos]=sum[pos]=0;
    }
    int get_id(int x) {
    	Node o=Node(x,x+1,0);
    	it=P.lower_bound(o);
    	if(it->l>x) --it;
    	return it->id;
    }
    
    void rotate(int pos) {
    	int x,y,p; y=fa[x=fa[pos]]; p=son[x][1]==pos;
    	if(y) son[y][son[y][1]==x]=pos; 
    	if(x==root) root=pos;
    	fa[pos]=y;
    	son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x;
    	son[pos][!p]=x; fa[x]=pos;
    	ud(x); ud(pos);
    }
    
    void splay(int pos) {
    	for(int x,y;fa[pos];rotate(pos)) {
    		y=fa[x=fa[pos]];
    		if(y) (son[x][1]==pos^son[y][1]==x)? rotate(pos):rotate(x);
    	}
    }
    
    int merge(int x,int y) {
    	if((ll)x*y==0) return x+y;
    	splay(x); splay(y);
    	while(son[x][1]) x=son[x][1];
    	splay(x);
    	son[x][1]=y; fa[y]=x;
    	ud(y); ud(x);
    	return x;
    }
    
    ll split(int pos,int x) {
    	splay(pos);
    	int ld=lc,rd=rc,l,r;
    	del(pos);
    	l=newnode(L[pos],x,0);
    	r=newnode(x+1,R[pos],0);
    	son[l][0]=ld; fa[ld]=l;
    	son[r][1]=rd; fa[rd]=r;
    	ud(l); ud(r);
    	root=merge(l,r);
    	return pr(l,r);
    }
    
    void cut(int pos) {
    	splay(pos);
    	fa[lc]=fa[rc]=0;
    	root=merge(lc,rc);
    	lc=rc=0;
    }
    
    int sep(int pos,int x) {
    	if(L[pos]==x&&R[pos]==x) return pos;
    	if(L[pos]!=x) pos=se(split(pos,x-1));
    	if(R[pos]!=x) pos=fi(split(pos,x));
    	return pos;
    }
    
    int qrank(int x) {
    	int pos=get_id(x);
    	splay(pos);
    	return sum[lc]+(x-L[pos]+1);
    }
    
    int qnum(int pos,int &x) {
    	if(x>sum[lc]&&x<=sum[lc]+num[pos]) return x-=sum[lc],pos;
    	if(x<=sum[lc]) return qnum(lc,x);
    	x-=sum[lc]+num[pos]; return qnum(rc,x);
    }
    
    int main() {
    	read(n); read(m);
    	newnode(1,n,0); root=1;
    	son[1][0]=newnode(1,0,1);
    	son[1][1]=newnode(n+1,n,1);
    	int op,x,y,pos,p,last=0;
    	For(i,1,m) {
    		read(op); read(x); x-=last;
    		if(op==1) {
    			read(y); y-=last;
    			G[y]=G[x]? G[x]:x; G[x]=0;
    			H[G[y]]=y;
    			last=qrank(G[y]);
    		}
    		else {
    			if(op!=4&&G[x]) x=G[x];
    			if(op==2) {
    				pos=get_id(x);
    				last=qrank(x);
    				pos=sep(pos,x);
    				cut(pos); cut(2);
    				root=merge(pos,root);
    				root=merge(2,pos);
    			}
    			else if(op==3) {
    				pos=get_id(x);
    				last=qrank(x);
    				pos=sep(pos,x);
    				cut(pos); cut(3);
    				root=merge(root,pos);
    				root=merge(root,3);
    			}
    			else {
    				pos=qnum(root,x);
    				x=x+L[pos]-1;
    				last=H[x]? H[x]:x;
    			}
    		}
    		printf("%d
    ",last);
    	}
    	return 0;
    }
    /*
    10 10
    1 2 11
    3 13
    2 5
    3 7
    2 8
    2 10
    2 11
    3 14
    2 18
    4 9
    */
    

      

  • 相关阅读:
    C#学习笔记-代理模式
    SqlDbx连接oracle
    C# 连接oracle,用32位client和64位Client,可能导致结果不同
    PHP&Java 调用C#的WCF
    DevExpress GridControl 控件二表连动
    SSAS 非重复计数
    Corn 表达式
    C# 实现Tree,包含parentId和children
    jsfiddle.net上的记录
    【慕课网实战】Spark Streaming实时流处理项目实战笔记十二之铭文升级版
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8110765.html
Copyright © 2011-2022 走看看