【NOI2005】维护数列(BSOI2246)

【NOI2005】维护数列

Description

   

Input

   

Output

   

Sample Input

Sample Output

Hint

   
   
   
   

Solution

先给上一个手打的样例,图片样例非常麻烦:

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM 
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM 

这道题蒟蒻花了一天半才A了过去,RE了不下二十次。

要A这道题的诀窍就是写。。。标记的下传是非常繁琐的,不过要注意合理的优化下传的方式。

最让人头痛的就是各种边界和标记了,当然,要是你把Splay写错了,那么,对不起,CtrlA+Delete。。。(根本没法调)

算了,上代码。

CODE

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
inline int read(){
	char c;int rec=0,f=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=-1;
	while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
	return rec*f;
}
int n,m,cnt,root;
int q[500005],c[500005];
struct Splay_Tree{
	int F,s[2];
	int size,val,sum,maxx,pmax[2];
	int C,R;
	inline void NewNode(int fa,int x){
		F=fa;C=R=0;size=1;
		val=sum=maxx=pmax[0]=pmax[1]=x;
		return ;
	}
}tree[500005];
inline void PMAX(int v,int f){
	tree[v].pmax[f]=max(tree[tree[v].s[f]].pmax[f],
	                tree[tree[v].s[f]].sum+tree[v].val+max(0,tree[tree[v].s[!f]].pmax[f]));
}
inline void Up(int v){
	tree[v].size=tree[tree[v].s[0]].size+1+tree[tree[v].s[1]].size;
	tree[v].sum=tree[tree[v].s[0]].sum+tree[v].val+tree[tree[v].s[1]].sum;
	tree[v].maxx=max(max(tree[tree[v].s[0]].maxx,tree[tree[v].s[1]].maxx),
	        max(0,tree[tree[v].s[0]].pmax[1])+tree[v].val+max(0,tree[tree[v].s[1]].pmax[0]));
	PMAX(v,0);PMAX(v,1);return ;
}
inline void Same(int v,int x){if(v==0)return ;
	tree[v].C=1;tree[v].val=x;tree[v].sum=x*tree[v].size;
	tree[v].maxx=tree[v].pmax[0]=tree[v].pmax[1]=max(x,tree[v].sum);
	return ;
}
inline void Rev(int v){if(v==0)return ;
	tree[v].R^=1;swap(tree[v].s[0],tree[v].s[1]);swap(tree[v].pmax[0],tree[v].pmax[1]);return ;
}
inline void Down(int v){
	if(tree[v].C){Same(tree[v].s[0],tree[v].val);Same(tree[v].s[1],tree[v].val);tree[v].C=0;}
	if(tree[v].R){Rev(tree[v].s[0]);Rev(tree[v].s[1]);tree[v].R=0;}
	return ;
}
inline void Lazy(int v){if(tree[v].F)Lazy(tree[v].F);Down(v);return ;}
inline void Rotate(int v){
	int p=tree[v].F,g=tree[p].F;
	int f1=(v==tree[p].s[1]),f2=(p==tree[g].s[1]),S=tree[v].s[!f1];
	tree[g].s[f2]=v;tree[v].F=g;
	tree[p].s[f1]=S;tree[S].F=p;
	tree[v].s[!f1]=p;tree[p].F=v;
	Up(p);return ;
}
inline void Splay(int v,int goal){Lazy(v);
	while(tree[v].F!=goal){
		int p=tree[v].F,g=tree[p].F;
		if(g!=goal)(v==tree[p].s[1])^(p==tree[g].s[1])?Rotate(v):Rotate(p);
		Rotate(v);
	}Up(v);if(!goal)root=v;
	return ;
}
inline int Build(int L,int R,int fa){
	if(L>R)return 0;
	int mid=(L+R)>>1,p=q[0]?q[q[0]--]:++cnt;
	tree[p].NewNode(fa,c[mid]);
	tree[p].s[0]=Build(L,mid-1,p);
	tree[p].s[1]=Build(mid+1,R,p);
	Up(p);return p;
}
inline void Re(int v){if(v==0)return ;q[++q[0]]=v;Re(tree[v].s[0]);Re(tree[v].s[1]);return ;}
int V;
inline void Find(int p){
	int v=root;
	while(tree[tree[v].s[0]].size+1!=p){
		Down(v);
		if (tree[tree[v].s[0]].size+1>=p)v=tree[v].s[0];
		else {p-=tree[tree[v].s[0]].size+1;v=tree[v].s[1];}
	}V=v;return ;
}
inline void Pre(int x,int y){Find(x);Splay(V,0);Find(y);Splay(V,root);return ;}
inline void Insert(int x,int y){Pre(x,x+1);tree[V].s[0]=Build(1,y,V);Up(V);Up(root);return ;}
inline void Delete(int x,int y){Pre(x-1,x+y);Re(tree[V].s[0]);tree[V].s[0]=0;Up(V);Up(root);return ;}
inline void Reverse(int x,int y){Pre(x-1,x+y);Rev(tree[V].s[0]);Up(V);Up(root);return ;}
inline void Make(int x,int y,int z){Pre(x-1,x+y);Same(tree[V].s[0],z);Up(V);Up(root);return ;}
inline int Get_sum(int x,int y){Pre(x-1,x+y);return tree[tree[V].s[0]].sum;}
int main(){
	tree[0].maxx=tree[0].pmax[0]=tree[0].pmax[1]=-0x3f3f3f3f;
	n=read();m=read();int i,x,y,z;char ch[15];
	for(i=1;i<=n;i++)c[i]=read();
	tree[++cnt].NewNode(0,-0x3f3f3f3f);
	tree[++cnt].NewNode(1,-0x3f3f3f3f);
	tree[1].s[1]=2;root=1;Insert(1,n);
	for(i=1;i<=m;i++){
		scanf("%s",ch);
		if (ch[0]=='M'){
			if (ch[2]=='X')cout<<tree[root].maxx<<'\n';
			else x=read(),y=read(),z=read(),Make(x+1,y,z);
		}
		else{
			x=read();y=read();x++;
			if (ch[0]=='I'){for(z=1;z<=y;z++)c[z]=read();Insert(x,y);}
			if (ch[0]=='D')Delete(x,y);
			if (ch[0]=='R')Reverse(x,y);
			if (ch[0]=='G')cout<<Get_sum(x,y)<<'\n';
		}
	}
	return 0;
}

(蒟蒻写了垃圾回收但是却没有调用,连续RE了七八次。。。)还有大神的80行维护数列,ORZ。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值