题目描述
维护一个数列,共7种操作:
1 INSERT x n a1 a2 .. An
在第x个数后插入n个数分别为a1 .. an;
2 DELETE x n
删除第x个数开始的n个数;
3 REVERSE x n
翻转第x个数开始的n个数的区间;
4 MAKE-SAME x n t
将第x个数开始的n个数统一改为t;
5 GET-SUM x n
输出第x个数开始的n个数的和;
6 GET x
输出第x个数的值;
7 MAX-SUM x n
输出第x个数开始的n个数的最大连续子序列和。
输入输出格式
输入格式:第1行为N,M,N表示初始序列中数的个数,M表示操作的个数。
第2行为N个数a1 .. An,表示初始序列。
第3行到第M+2行,每行一个操作。
输出格式:输出5 GET-SUM,6 GET,7 MAX-SUM操作的结果。
输入输出样例
9 8 2 -6 3 5 1 -5 -3 6 3 GET-SUM 5 4 MAX-SUM 1 9 INSERT 8 3 -5 7 2 DELETE 12 1 MAKE-SAME 3 3 2 REVERSE 3 6 GET 5 MAX-SUM 1 11
-1 10 -5 10
说明
共20组数据,每组数据随机生成,保证每个时刻数列里的数不超过200000个,任何一个输入的数字均在-1000~1000之间,结果不超过2^30。
第1~2组1≤N≤51≤M≤10
第3~4组1≤N≤101≤M≤20
第5~6组1≤N≤201≤M≤50
第7~8组1≤N≤501≤M≤100
第9~10组1≤N≤1001≤M≤500
第11~12组1≤N≤10001≤M≤1000
第13~14组1≤N≤50001≤M≤2000
第15~16组1≤N≤10000 1≤M≤5000
第17~18组1≤N≤100000 1≤M≤10000
第19~20组1≤N≤200000 1≤M≤20000
与 [NOI2005]维护数列 差不多,只不过多了一个操作。
splay没话说,什么区间 [ l , r ] ,要将 l-1 , r+1 旋转到根,就不讲了,简单。
标记下传:
其他还好,旋转标记极坑!
这坑了我半天,到现在也没想出为啥,只知道是对的。。。
代码应该是:
if(a[rt].flag){
if(a[rt].son[0]){
a[a[rt].son[0]].flag^=1;
swap(a[a[rt].son[0]].suml,a[a[rt].son[0]].sumr);
swap(a[a[rt].son[0]].son[0],a[a[rt].son[0]].son[1]);
}
if(a[rt].son[1]){
a[a[rt].son[1]].flag^=1;
swap(a[a[rt].son[1]].suml,a[a[rt].son[1]].sumr);
swap(a[a[rt].son[1]].son[0],a[a[rt].son[1]].son[1]);
}
a[rt].flag^=1;
}
而不是:
if(a[rt].flag){
a[a[rt].son[0]].flag^=1;a[a[rt].son[1]].flag^=1;a[rt].flag^=1;
swap(a[rt].suml,a[rt].sumr);swap(a[rt].son[0],a[rt].son[1]);
}
于是打标记就是:
void reverge(int rt,int l,int r){
int front=kth(rt,l),next=kth(rt,r+2);
split(front,next);
int k=a[next].son[0];
if(!k)return;
a[k].flag^=1;
swap(a[k].son[0],a[k].son[1]);
swap(a[k].suml,a[k].sumr);
pushup(next);pushup(front);
}
虽然不知道为什么,但是AC了,于是:
信息学竞赛不需要证明。。。
附上超长代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define MAXN 500010
#define MAX 999999999
using namespace std;
queue<int> q;
int n,m,size=1,root,val[MAXN];
struct node{
int f,s,flag,set,son[2];
int v,w,sum,suml,sumr;
}a[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline void clean(int rt){
a[rt].son[0]=a[rt].son[1]=a[rt].f=a[rt].s=a[rt].flag=a[rt].v=a[rt].w=0;
a[rt].sum=a[rt].suml=a[rt].sumr=-MAX;
}
inline void pushup(int rt){
if(!rt)return;
a[rt].s=a[a[rt].son[0]].s+a[a[rt].son[1]].s+1;
a[rt].w=a[a[rt].son[0]].w+a[a[rt].son[1]].w+a[rt].v;
a[rt].suml=max(a[a[rt].son[0]].suml,a[a[rt].son[0]].w+a[rt].v+max(0,a[a[rt].son[1]].suml));
a[rt].sumr=max(a[a[rt].son[1]].sumr,a[a[rt].son[1]].w+a[rt].v+max(0,a[a[rt].son[0]].sumr));
a[rt].sum=max(a[rt].v+max(0,a[a[rt].son[0]].sumr)+max(0,a[a[rt].son[1]].suml),max(a[a[rt].son[0]].sum,a[a[rt].son[1]].sum));
}
inline void pushdown(int rt){
if(!rt)return;
if(a[rt].set!=-MAX){
if(a[rt].son[0]){
a[a[rt].son[0]].set=a[a[rt].son[0]].v=a[rt].set;
a[a[rt].son[0]].w=a[rt].set*a[a[rt].son[0]].s;
a[a[rt].son[0]].suml=a[a[rt].son[0]].sumr=a[a[rt].son[0]].sum=max(a[a[rt].son[0]].set,a[a[rt].son[0]].w);
}
if(a[rt].son[1]){
a[a[rt].son[1]].set=a[a[rt].son[1]].v=a[rt].set;
a[a[rt].son[1]].w=a[rt].set*a[a[rt].son[1]].s;
a[a[rt].son[1]].suml=a[a[rt].son[1]].sumr=a[a[rt].son[1]].sum=max(a[a[rt].son[1]].set,a[a[rt].son[1]].w);
}
a[rt].set=-MAX;
a[rt].flag=0;
}
if(a[rt].flag){
if(a[rt].son[0]){
a[a[rt].son[0]].flag^=1;
swap(a[a[rt].son[0]].suml,a[a[rt].son[0]].sumr);
swap(a[a[rt].son[0]].son[0],a[a[rt].son[0]].son[1]);
}
if(a[rt].son[1]){
a[a[rt].son[1]].flag^=1;
swap(a[a[rt].son[1]].suml,a[a[rt].son[1]].sumr);
swap(a[a[rt].son[1]].son[0],a[a[rt].son[1]].son[1]);
}
a[rt].flag^=1;
}
}
inline int newnode(int x){
int rt;
if(q.empty())rt=size++;
else{
rt=q.front();
q.pop();
}
a[rt].v=x;
a[rt].suml=a[rt].sumr=a[rt].sum=-MAX;
a[rt].flag=0;a[rt].set=-MAX;
return rt;
}
inline void turn(int rt,int k){
int x=a[rt].f,y=a[x].f;
pushdown(x);pushdown(rt);
a[x].son[k^1]=a[rt].son[k];
if(a[rt].son[k])a[a[rt].son[k]].f=x;
a[rt].f=y;
if(y)a[y].son[a[y].son[1]==x]=rt;
a[x].f=rt;
a[rt].son[k]=x;
pushup(x);pushup(rt);
}
void splay(int rt,int ancestry){
while(a[rt].f!=ancestry){
int x=a[rt].f,y=a[x].f;
if(y==ancestry)turn(rt,a[x].son[0]==rt);
else{
int k=a[y].son[0]==x?1:0;
if(a[x].son[k]==rt){turn(rt,k^1);turn(rt,k);}
else{turn(x,k);turn(rt,k);}
}
}
if(ancestry==0)root=rt;
}
int kth(int rt,int k){
if(a[rt].s<k)return 0;
while(1){
pushdown(rt);
int y=a[rt].son[0];
if(k>a[y].s+1){
rt=a[rt].son[1];
k-=a[y].s+1;
}
else if(k<=a[y].s)rt=y;
else return rt;
}
}
int buildtree(int l,int r){
if(l>r)return 0;
int rt,mid=l+r>>1,lson=0,rson=0;
lson=buildtree(l,mid-1);
rt=newnode(val[mid]);
rson=buildtree(mid+1,r);
a[rt].son[0]=lson;
a[rt].son[1]=rson;
if(lson)a[lson].f=rt;
if(rson)a[rson].f=rt;
pushup(rt);
return rt;
}
inline void split(int front,int next){
splay(front,0);splay(next,front);
}
inline void insert(int rt,int x,int y){
int front=kth(rt,x+1),next=kth(rt,x+2);
split(front,next);
int k=a[next].son[0];
rt=buildtree(1,y);
a[next].son[0]=rt;a[rt].f=next;
pushup(next);pushup(front);
}
void delete_x(int rt){
if(!rt)return;
q.push(rt);
if(a[rt].son[0])delete_x(a[rt].son[0]);
if(a[rt].son[1])delete_x(a[rt].son[1]);
clean(rt);
}
inline void remove(int rt,int l,int r){
int front=kth(rt,l),next=kth(rt,r+2);
split(front,next);
int k=a[next].son[0];
if(k)delete_x(k);
a[next].son[0]=0;
pushup(next);pushup(front);
}
void reverge(int rt,int l,int r){
int front=kth(rt,l),next=kth(rt,r+2);
split(front,next);
int k=a[next].son[0];
if(!k)return;
a[k].flag^=1;
swap(a[k].son[0],a[k].son[1]);
swap(a[k].suml,a[k].sumr);
pushup(next);pushup(front);
}
void same(int rt,int l,int r,int x){
int front=kth(rt,l),next=kth(rt,r+2);
split(front,next);
int k=a[next].son[0];
if(!k)return;
a[k].set=a[k].v=x;
a[k].w=x*a[k].s;
a[k].suml=a[k].sumr=a[k].sum=max(x,a[k].w);
pushup(next);pushup(front);
}
int main(){
int x,y,k;
char ch[20];
n=read();m=read();
for(int i=1;i<=n;i++)val[i]=read();
val[0]=val[n+1]=0;
clean(0);clean(n+1);
root=buildtree(0,n+1);
while(m--){
scanf("%s",ch);x=read();
switch(ch[0]){
case 'I':{
y=read();
for(int i=1;i<=y;i++)val[i]=read();
insert(root,x,y);
break;
}
case 'D':y=read();remove(root,x,x+y-1);break;
case 'R':y=read();reverge(root,x,x+y-1);break;
case 'G':{
if(ch[3]=='-'){
y=read();
int front=kth(root,x),next=kth(root,x+y+1);
split(front,next);
int k=a[next].son[0];
printf("%d\n",a[k].w);
}
else printf("%d\n",a[kth(root,x+1)].v);
break;
}
case 'M':{
y=read();
if(ch[4]=='-'){
k=read();
same(root,x,x+y-1,k);
}
else{
int front=kth(root,x),next=kth(root,x+y+1);
split(front,next);
int k=a[next].son[0];
printf("%d\n",a[k].sum);
}
break;
}
}
}
return 0;
}
clean(rt);