zoukankan      html  css  js  c++  java
  • 平衡树区间操作板子

    前几天知道平衡树也能像线段树一样实现操作。
    并且还能轻易实现一些线段树很难做到的东西。
    如区间翻转。

    以下题目本人均用\(fhq-treap\)完成

    先完成文艺平衡树序列终结者[CQOI2014]排序机械臂
    接下来的一道经典例题大概就是上面的三道的总和
    [NOI2005] 维护数列

    题目大意

    实现一个数据结构,支持一下操作:

    • 在任意位置插入一堆数
    • 在任意位置删除一堆数
    • 在任意位置修改一堆数
    • 翻转任意区间
    • 查询任意区间和
    • 查询整个序列的最大子段和

      做完先前三题你就能知道大致思路了,下面讲述一些注意事项。
    1. 对于插入,很显然不能一个一个插,你可以先把要插入的\(tot\)个数形成一棵平衡树,然后与原序列的平衡树合并。
      但这样会\(T\)\(20pts\),其实你就可以像线段树那样“分治建树”,可以很巧妙的将插入复杂度由\(O(totlog_2tot)\)降为\((log^2tot)\)
    2. 此题卡空间,在删除时应该“回收利用”节点编号。
    3. 一些零碎的细节:最大子段和不能为空,记得\(pushdown\)\(update\),不要操作空节点等。
    code:
    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e5+10;
    int n,T,cnt,rt;
    int ls[N],rs[N],val[N],siz[N],pfer[N];
    int sum[N],lmx[N],rmx[N],a[N];
    int rev[N],tag[N],dat[N];
    int sk[N],top;
    bool ct[N];
    int read(){
    	int A=0,F=1;
    	char C=getchar();
    	while(C<'0'||C>'9'){if(C=='-')F=-1;C=getchar();}
    	while(C>='0'&&C<='9'){A=(A<<1)+(A<<3)+C-'0';C=getchar();}
    	return A*F;
    }
    int New(int k){
    	int p=top?sk[top--]:++cnt;
    	ls[p]=rs[p]=rev[p]=tag[p]=ct[p]=0;
    	sum[p]=k;val[p]=k;
    	lmx[p]=max(k,0);
    	rmx[p]=max(k,0);
    	dat[p]=k;
    	siz[p]=1;pfer[p]=rand()*rand();
    	return p;
    }
    void update(int p){
    	if(!p)return;
    	siz[p]=siz[ls[p]]+siz[rs[p]]+1;
    	sum[p]=sum[ls[p]]+sum[rs[p]]+val[p];
    	lmx[p]=max(max(lmx[ls[p]],sum[ls[p]]+val[p]+lmx[rs[p]]),0);
    	rmx[p]=max(max(rmx[rs[p]],sum[rs[p]]+val[p]+rmx[ls[p]]),0);
    	dat[p]=max(val[p],val[p]+rmx[ls[p]]+lmx[rs[p]]);
    	if(ls[p])dat[p]=max(dat[p],dat[ls[p]]);
    	if(rs[p])dat[p]=max(dat[p],dat[rs[p]]);
    }
    void Re(int p){
    	if(!p)return;
    	swap(ls[p],rs[p]);
    	swap(lmx[p],rmx[p]);
    	rev[p]^=1;
    }
    void Co(int p,int v){
    	val[p]=tag[p]=v;
    	sum[p]=siz[p]*v;
    	lmx[p]=rmx[p]=max(0,sum[p]);
    	dat[p]=max(v,sum[p]);
    	ct[p]=1;
    }
    void pushdown(int p){
    	if(!p)return;
    	if(rev[p]){
    		if(ls[p])Re(ls[p]);
    		if(rs[p])Re(rs[p]);
    		rev[p]=0;
    	}
    	if(ct[p]){
    		if(ls[p])Co(ls[p],tag[p]);
    		if(rs[p])Co(rs[p],tag[p]);
    		tag[p]=ct[p]=0;
    	}
    }
    void split(int p,int sz,int &x,int &y){
    	if(!p){x=y=0;return;}
    	pushdown(p);
    	if(siz[ls[p]]+1<=sz){x=p;split(rs[p],sz-siz[ls[p]]-1,rs[p],y);}
    	else{y=p;split(ls[p],sz,x,ls[p]);}
    	update(p);
    }
    int merge(int x,int y){
    	if(!x||!y)return x+y;
    	if(pfer[x]>pfer[y]){
    		pushdown(x);
    		rs[x]=merge(rs[x],y);
    		update(x);
    		return x;
    	}
    	else{
    		pushdown(y);
    		ls[y]=merge(x,ls[y]);
    		update(y);
    		return y;
    	}
    }
    void recycle(int p){
    	if(!p)return;
    	sk[++top]=p;
    	recycle(ls[p]);
    	recycle(rs[p]);
    }
    void del(int l,int r){
    	int x,y,z;
    	split(rt,l-1,x,y);
    	split(y,r-l+1,y,z);
    	recycle(y);
    	rt=merge(x,z);
    }
    void modify(int l,int r,int k){
    	int x,y,z;
    	split(rt,l-1,x,y);
    	split(y,r-l+1,y,z);
    	Co(y,k);
    	rt=merge(merge(x,y),z);
    }
    void reverse(int l,int r){
    	int x,y,z;
    	split(rt,l-1,x,y);
    	split(y,r-l+1,y,z);
    	Re(y);
    	rt=merge(merge(x,y),z);
    }
    int qsum(int l,int r){
    	int x,y,z,ans;
    	split(rt,l-1,x,y);
    	split(y,r-l+1,y,z);
    	ans=sum[y];
    	rt=merge(merge(x,y),z);
    	return ans;
    }
    int  Buld(int l,int r){
    	if(l==r)return New(a[l]);
    	int mid=l+r>>1,now;
    	now=merge(Buld(l,mid),Buld(mid+1,r));
    	return now;
    }
    int main(){
    	srand(time(0));
    //	freopen("P2042_8.in","r",stdin);
    //	freopen("ans.out","w",stdout);
    //	double st=clock();
    	n=read();T=read();
    	for(int i=1;i<=n;i++){
    		int x;
    		x=read();
    		rt=merge(rt,New(x));
    	}
    	while(T--){
    		char op[30];
    		scanf("%s",op);
    		int w,c,x;
    		if(op[0]=='I'){
    			w=read();c=read();
    			int TpT=0;
    			for(int i=1;i<=c;i++)a[i]=read();
    			TpT=Buld(1,c);
    			int x,y,z;
    			split(rt,w,x,y);
    			rt=merge(merge(x,TpT),y);
    		}
    		else if(op[0]=='D'){
    			w=read();c=read();
    			del(w,w+c-1);
    		}
    		else if(op[2]=='K'){
    			w=read();c=read();x=read();
    			modify(w,w+c-1,x);
    		}
    		else if(op[0]=='R'){
    			w=read();c=read();
    			reverse(w,w+c-1);
    		}
    		else if(op[0]=='G'){
    			w=read();c=read();
    			printf("%d\n",qsum(w,w+c-1));
    		}
    		else if(op[0]=='M')printf("%d\n",dat[rt]);
    	}
    	//cout<<clock()-st;
    	return 0;
    }
    
  • 相关阅读:
    《转》12个Sublime Text使用技巧
    Sublime Text 3 快捷键总结
    IIS发布的网站常见的问题汇总
    sublime text 3 安装卸载插件和取消启动检查更新
    sublime text 3 环境变量的配置、安装Package Control、汉化和注册
    github贡献开源项目
    github团队协作
    github desktop的使用
    GitHub网站操作
    HTML中的SVG
  • 原文地址:https://www.cnblogs.com/Xxhdjr/p/14356176.html
Copyright © 2011-2022 走看看