• [NOI2005]维护数列


    题目:BZOJ1500、洛谷P2042、Vijos P1835、codevs1758。

    题目大意:
    给你一个数列,实现以下操作。


    解题思路:
    非旋Treap维护数列即可。
    前面5个都是基本的平衡树序列操作(第5个维护一个区间和即可)。
    第6个要求最大子段和,则我们需要维护以当前节点为子树的子段和,当前子树的最大前缀和和最大后缀和,才能转移出正确的最大子段和。(具体如何维护详见代码)
    对于旋转操作,需要把前缀和后缀交换一下。
    还有要注意:
    1. 内存不能开太大,会MLE,要回收被删除的节点。
    2. 插入时不要一个一个merge,先按照笛卡尔树的建树方式建树(O(n)),然后直接merge根即可。

    C++ Code:

    #include<bits/stdc++.h>
    inline int max(int a,int b){return a>b?a:b;}
    inline void swap(int& a,int& b){int c=a;a=b,b=c;}
    inline int readint(){
    	int c=getchar(),d=0,b=0;
    	for(;!isdigit(c);c=getchar())b=c=='-';
    	for(;isdigit(c);c=getchar())d=(d<<3)+(d<<1)+(c^'0');
    	return b?-d:d;
    }
    struct node{
    	int ls,rs,s,lm,rm,sm,smx,rot,r,tag,sz;
    	inline void Cng(int val){
    		s=val;
    		sm=sz*val;
    		lm=rm=max(sm,0);
    		smx=max(sm,s);
    		tag=1;
    	}
    	inline void rev(){
    		swap(ls,rs);
    		swap(lm,rm);
    		rot^=1;
    	}
    }a[500005];
    struct Memory_pool{
    	int p[500005],top;
    	Memory_pool(){
    		for(int i=1;i<=500004;++i)p[i]=i;
    		top=500004;
    	}
    	inline int New(){return p[top--];}
    	inline void Del(int x){p[++top]=x;}
    }P;
    int n,m,rt,sta[500005],top=0;
    inline void pushdown(int x){
    	if(a[x].rot){
    		a[x].rot=0;
    		if(a[x].ls)a[a[x].ls].rev();
    		if(a[x].rs)a[a[x].rs].rev();
    	}
    	if(a[x].tag){
    		a[x].tag=0;
    		if(a[x].ls)a[a[x].ls].Cng(a[x].s);
    		if(a[x].rs)a[a[x].rs].Cng(a[x].s);
    	}
    }
    inline void update(int x){
    	int ls=a[x].ls,rs=a[x].rs,s=a[x].s;
    	if(ls&&rs){
    		a[x].sz=a[ls].sz+a[rs].sz+1;
    		a[x].sm=a[ls].sm+a[rs].sm+s;
    		a[x].smx=max(a[ls].smx,a[rs].smx);
    		a[x].smx=max(a[x].smx,a[ls].rm+s+a[rs].lm);
    		a[x].lm=max(a[ls].lm,a[ls].sm+s+a[rs].lm);
    		a[x].rm=max(a[rs].rm,a[rs].sm+s+a[ls].rm);
    	}else
    	if(ls){
    		a[x].sz=a[ls].sz+1;
    		a[x].sm=a[ls].sm+s;
    		a[x].smx=max(a[ls].smx,a[ls].rm+s);
    		a[x].lm=max(a[ls].lm,a[ls].sm+s);
    		a[x].rm=max(a[ls].rm+s,0);
    	}else
    	if(rs){
    		a[x].sz=a[rs].sz+1;
    		a[x].sm=a[rs].sm+s;
    		a[x].smx=max(a[rs].smx,a[rs].lm+s);
    		a[x].rm=max(a[rs].rm,a[rs].sm+s);
    		a[x].lm=max(a[rs].lm+s,0);
    	}else{
    		a[x].sz=1;
    		a[x].sm=a[x].smx=s;
    		a[x].lm=a[x].rm=max(s,0);
    	}
    }
    int build(int n){
    	int x,pre;
    	for(int i=1;i<=n;++i){
    		int f=readint();
    		int ff=max(f,0);
    		a[x=P.New()]=(node){0,0,f,ff,ff,f,f,0,rand(),0,1};
    		for(pre=0;top&&a[sta[top]].r>a[x].r;--top)update(pre=sta[top]);
    		if(top)a[sta[top]].rs=x;
    		a[sta[++top]=x].ls=pre;
    	}
    	while(top)update(sta[top--]);
    	return sta[1];
    }
    void split(int u,int k,int& x,int& y){
    	if(!k){
    		x=0,y=u;
    		return;
    	}
    	if(k==a[u].sz){
    		x=u,y=0;
    		return;
    	}
    	pushdown(u);
    	if(a[a[u].ls].sz>=k)split(a[u].ls,k,x,a[u].ls),y=u;else
    	split(a[u].rs,k-a[a[u].ls].sz-1,a[u].rs,y),x=u;
    	update(u);
    }
    int merge(int x,int y){
    	if(x)pushdown(x);
    	if(y)pushdown(y);
    	if(!x||!y)return x|y;
    	if(a[x].r<a[y].r){
    		a[x].rs=merge(a[x].rs,y);
    		update(x);
    		return x;
    	}
    	a[y].ls=merge(x,a[y].ls);
    	update(y);
    	return y;
    }
    void dispose(int now){
    	if(!now)return;
    	dispose(a[now].ls);
    	dispose(a[now].rs);
    	P.Del(now);
    }
    int main(){
    	n=readint(),m=readint();
    	a[0]=(node){0,0,0,0,0,0,0,0,0,0,0};
    	srand(20170607);
    	rt=build(n);
    	while(m--){
    		static char s[100];
    		int tot;
    		scanf("%s",s);
    		if(s[0]=='I'){
    			tot=readint();int rtn=build(readint()),x,y;
    			split(rt,tot,x,y);
    			rt=merge(merge(x,rtn),y);
    		}else
    		if(s[0]=='D'){
    			tot=readint(),n=readint();
    			int x,y,z;
    			split(rt,tot-1,x,y);
    			split(y,n,y,z);
    			dispose(y);
    			rt=merge(x,z);
    		}else
    		if(s[0]=='M'&&s[2]=='K'){
    			tot=readint(),n=readint();
    			int x,y,z;
    			split(rt,tot-1,x,y);
    			split(y,n,y,z);
    			a[y].Cng(readint());
    			rt=merge(merge(x,y),z);
    		}else
    		if(s[0]=='R'){
    			tot=readint(),n=readint();
    			int x,y,z;
    			split(rt,tot-1,x,y);
    			split(y,n,y,z);
    			a[y].rev();
    			rt=merge(merge(x,y),z);
    		}else
    		if(s[0]=='G'){
    			tot=readint(),n=readint();
    			int x,y,z;
    			split(rt,tot-1,x,y);
    			split(y,n,y,z);
    			printf("%d
    ",a[y].sm);
    			rt=merge(merge(x,y),z);
    		}else printf("%d
    ",a[rt].smx);
    	}
    	return 0;
    }
    
  • 相关阅读:
    (转)排序算法——归并排序与递归
    在serviceImpl里使用自身的方法
    hibernate manytoone中的lazy EAGER
    autowire异常的三个情况
    (转)js的call和apply
    mysql创建外键出错(注意数据库表字段排序)
    easyui datagrid
    ava.lang.NullPointerException的一般解决方法
    spring简单事务管理器
    关于使用注解出现BeanCreationException或者NameNotFoundException的解决方法
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8876703.html
Copyright © 2020-2023  润新知