【NOI2005】维护数列(BSOI2246)

来源:互联网 发布:手机屏幕测试软件 编辑:程序博客网 时间:2024/06/05 02:50

【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。


0 0
原创粉丝点击