1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 14433 Solved: 4701
[ Submit][ Status][ Discuss]
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
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
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
Sample Output
-1
10
1
10
10
1
10
HINT
Source
终于A掉这道题了,调了快一个小时...splay有个地方写错了导致rotate着的时候有一个儿子掉了...其他就没什么好说的,因为这道题是splay裸题,算是代码题(其实也不算太长).看一下代码的update就能懂了怎么求最大子段和了.
纪念一下:
RunID | User | Problem | Result | Memory | Time | Language | Code_Length | Submit_Time |
2186510 | MaxMercer | 1500 | Accepted | 28184 kb | 4360 ms | C++/Edit | 5492 B | 2017-07-25 10:45:55 |
#include<stdio.h>
#include<algorithm>
using namespace std;
const int inf=(1<<29);
const int maxn=500005;
char ss[20];
int n,T,newone,tot,a[maxn],rev[maxn],tag[maxn],w[maxn],s[maxn],root;
int _recycle[maxn],_recycle_top,c[maxn][2],fa[maxn],siz[maxn],sum[maxn],lmax[maxn],rmax[maxn],ans[maxn];
inline const int read(){
register int f=1,x=0;
register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
inline int newnode(){
if(_recycle_top) newone=_recycle[_recycle_top--];
else newone=++tot;
c[newone][0]=c[newone][1]=fa[newone]=0;
rev[newone]=tag[newone]=0,siz[newone]=1;
lmax[newone]=rmax[newone]=sum[newone]=w[newone]=-inf;
return newone;
}
inline void reverse(int x){
if(!x) return;
swap(lmax[x],rmax[x]);
swap(c[x][0],c[x][1]);
rev[x]^=1;
}
inline void replace(int x,int val){
w[x]=val;sum[x]=siz[x]*val;
lmax[x]=rmax[x]=ans[x]=max(val,siz[x]*val);
tag[x]=1;
}
inline void update(int x){
if(!x) return;
siz[x]= siz[c[x][0]]+siz[c[x][1]]+1;
sum[x]= sum[c[x][0]]+sum[c[x][1]]+w[x];
lmax[x]=max(lmax[c[x][0]],sum[c[x][0]]+w[x]+max(lmax[c[x][1]],0));
rmax[x]=max(rmax[c[x][1]],sum[c[x][1]]+w[x]+max(rmax[c[x][0]],0));
ans[x]= max(max(ans[c[x][0]],ans[c[x][1]]),max(rmax[c[x][0]],0)+w[x]+max(lmax[c[x][1]],0));
}
inline void pushdown(int x){
if(rev[x]){
if(c[x][0]) reverse(c[x][0]);
if(c[x][1]) reverse(c[x][1]);
rev[x]=0;
}
if(tag[x]){
if(c[x][0]) replace(c[x][0],w[x]);
if(c[x][1]) replace(c[x][1],w[x]);
tag[x]=0;
}
}
inline void rotate(int x,int &_wanna){
int y=fa[x],z=fa[y];
int l=(c[y][0]!=x),r=l^1;
if(y!=_wanna) c[z][c[z][0]!=y]=x;
else _wanna=x;
fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
c[y][l]=c[x][r],c[x][r]=y;
update(y),update(x);
}
inline void splay(int x,int &_wanna){
int top=0;
s[++top]=x;
for(int i=x;fa[i];i=fa[i]) s[++top]=fa[i];
for(int i=top;i;i--) pushdown(s[i]);
for(int f;x!=_wanna;rotate(x,_wanna))
if((f=fa[x])!=_wanna)
rotate(((c[f][1]==x^c[fa[f]][1]==f)?x:f),_wanna);
}
void build(int lf,int rg,int who){
int mid=(lf+rg)>>1;
w[who]=a[mid];
if(lf==rg) {sum[who]=lmax[who]=rmax[who]=ans[who]=w[who];siz[who]=1;return;}
if(lf<mid) {c[who][0]=newnode();fa[c[who][0]]=who;build(lf,mid-1,c[who][0]);}
if(rg>mid) {c[who][1]=newnode();fa[c[who][1]]=who;build(mid+1,rg,c[who][1]);}
update(who);
}
int find(int k,int x){
pushdown(k);
if(x-1==siz[c[k][0]]) return k;
else if(x>siz[c[k][0]]+1) return find(c[k][1],x-siz[c[k][0]]-1);
else return find(c[k][0],x);
}
inline void Reverse(int x,int num){
x=find(root,x),splay(x,root);
int y=find(c[x][1],num+1);splay(y,c[x][1]);
reverse(c[y][0]);
update(y),update(x);
}
inline void Replace(int x,int num,int z){
x=find(root,x),splay(x,root);
int y=find(c[x][1],num+1);splay(y,c[x][1]);
replace(c[y][0],z);
update(y),update(x);
}
void erase(int x){
if(!x) return;
_recycle[++_recycle_top]=x;
if(c[x][0]) erase(c[x][0]);
if(c[x][1]) erase(c[x][1]);
}
inline void del(int x,int num){
x=find(root,x),splay(x,root);
int y=find(c[x][1],num+1);splay(y,c[x][1]);
erase(c[y][0]);
fa[c[y][0]]=c[y][0]=0;
update(y),update(x);
}
inline void insert(int x,int num){
for(register int i=1;i<=num;i++) a[i]=read();
x=find(root,x+1),splay(x,root);
int y=find(c[x][1],1);splay(y,c[x][1]);
c[y][0]=newnode();fa[c[y][0]]=y;
build(1,num,c[y][0]);
update(y),update(x);
}
inline void init(){
n=read(),T=read();
for(register int i=1;i<=n;i++) a[i]=read();
lmax[0]=rmax[0]=ans[0]=-inf;root=1,tot=2;
fa[1]=0,lmax[1]=rmax[1]=ans[1]=sum[1]=w[1]=-inf,c[1][1]=2,siz[1]=2;
fa[2]=1,lmax[2]=rmax[2]=ans[2]=sum[2]=w[2]=-inf,fa[2]=1,siz[1]=1;
c[2][0]=newnode(),fa[c[2][0]]=2,build(1,n,c[2][0]);
update(2),update(1);
}
int main(){
init();
while(T--){
int x,y,z;
scanf("%s",ss);
if(ss[0]=='I'){
x=read(),y=read();
insert(x,y);
}
if(ss[0]=='D'){
x=read(),y=read();
del(x,y);
}
if(ss[4]=='-'){
x=read(),y=read(),z=read();
Replace(x,y,z);
}
if(ss[0]=='R'){
x=read(),y=read();
Reverse(x,y);
}
if(ss[0]=='G'){
x=read(),y=read();
x=find(root,x);splay(x,root);
y=find(c[x][1],y+1);splay(y,c[x][1]);
printf("%d\n",sum[c[y][0]]);
}
if(ss[2]=='X') printf("%d\n",ans[root]);
}
return 0;
}