【NOI2005】维护数列
Description
Input
Output
Sample Input
Sample Output
Hint
Solution
先给上一个手打的样例,图片样例非常麻烦:
(蒟蒻写了垃圾回收但是却没有调用,连续RE了七八次。。。)还有大神的80行维护数列,ORZ。
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。