Description
请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线‘ _ ’表示实际输入文件中的空格)
1. 插入 INSERT_posi_tot_c1_c2_…_ctot 在当前数列的第posi个数字后插入tot个数字:c1, c2, …, ctot;若在数列首插入,则posi为0
2. 删除 DELETE_posi_tot 从当前数列的第posi个数字开始连续删除tot个数字
3. 修改 MAKE-SAME_posi_tot_c 将当前数列的第posi个数字开始的连续tot个数字统一修改为c
4. 翻转 REVERSE_posi_tot 取出从当前数列的第posi个数字开始的tot个数字,翻转后放入原来的位置
5. 求和 GET-SUM_posi_tot 计算从当前数列开始的第posi个数字开始的tot个数字的和并输出
6. 求和最大的子列 MAX-SUM 求出当前数列中和最大的一段子列,并输出最大和
Input
输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
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
Sample Output
-1
10
1
10
Data Constraint
Hint
样例说明请点这里
【数据规模和约定】
你可以认为在任何时刻,数列中至少有1个数。
输入数据一定是正确的,即指定位置的数在数列中一定存在。
50%的数据中,任何时刻数列中最多含有30 000个数;
100%的数据中,任何时刻数列中最多含有500 000个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,M ≤20 000,插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Solution
这题真的调试了一万年……
经典的Splay操作,维护子序列的话就维护一下子树前后缀的最大值,在合并到父亲上即可。
Code
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5e5+3,inf=1e9;
int root,tot;
int a[N],fa[N],key[N],size[N],s[N][2];
int sum[N],c[N],mx[N],pre[N],suf[N],back[N];
bool rev[N];
inline int read()
{
int X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
inline void write(int x)
{
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline int max(int x,int y)
{
return x>y?x:y;
}
inline bool pd(int x)
{
return x==s[fa[x]][1];
}
inline void newnode(int &v,int val,int p)
{
if(back[0]) v=back[back[0]--]; else v=++tot;
sum[v]=mx[v]=key[v]=val;
pre[v]=suf[v]=max(0,val);
size[v]=1,fa[v]=p,c[v]=inf;
s[v][0]=s[v][1]=rev[v]=0;
}
inline void reverse(int v)
{
if(!v) return;
swap(s[v][0],s[v][1]);
swap(pre[v],suf[v]);
rev[v]^=1;
}
inline void modify(int v,int val)
{
if(!v) return;
sum[v]=size[v]*val,c[v]=key[v]=val;
if(val>0) mx[v]=pre[v]=suf[v]=sum[v]; else
pre[v]=suf[v]=0,mx[v]=val;
}
inline void update(int v)
{
sum[v]=sum[s[v][0]]+sum[s[v][1]]+key[v];
size[v]=size[s[v][0]]+size[s[v][1]]+1;
pre[v]=max(pre[s[v][0]],sum[s[v][0]]+key[v]+pre[s[v][1]]);
suf[v]=max(suf[s[v][1]],sum[s[v][1]]+key[v]+suf[s[v][0]]);
mx[v]=max(0,suf[s[v][0]])+key[v]+max(0,pre[s[v][1]]);
if(s[v][0]) mx[v]=max(mx[v],mx[s[v][0]]);
if(s[v][1]) mx[v]=max(mx[v],mx[s[v][1]]);
}
inline void down(int v)
{
if(rev[v])
{
reverse(s[v][0]),reverse(s[v][1]);
rev[v]=false;
}
if(c[v]<inf)
{
modify(s[v][0],c[v]),modify(s[v][1],c[v]);
c[v]=inf;
}
}
inline void build(int &v,int l,int r,int p)
{
if(l>r) return;
int mid=(l+r)>>1;
newnode(v,a[mid],p);
build(s[v][0],l,mid-1,v);
build(s[v][1],mid+1,r,v);
update(v);
}
inline void rotate(int x)
{
down(x);
int y=fa[x],w=pd(x);
if(s[y][w]=s[x][w^1]) fa[s[x][w^1]]=y;
if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;
s[fa[y]=x][w^1]=y;
update(y);
}
inline void splay(int x,int k)
{
for(int y;(y=fa[x])^k;rotate(x))
if(fa[y]^k) rotate(pd(x)==pd(y)?y:x);
update(x);
if(!k) root=x;
}
inline int kth(int v,int k)
{
down(v);
if(size[s[v][0]]+1==k) return v;
if(k<=size[s[v][0]]) return kth(s[v][0],k);
return kth(s[v][1],k-size[s[v][0]]-1);
}
inline void change(int l,int r,int val)
{
splay(kth(root,l-1),0);
splay(kth(root,r+1),root);
modify(s[s[root][1]][0],val);
}
inline int get_sum(int l,int r)
{
splay(kth(root,l-1),0);
splay(kth(root,r+1),root);
return sum[s[s[root][1]][0]];
}
inline void insert(int x,int y)
{
splay(kth(root,x),0);
splay(kth(root,x+1),root);
build(s[s[root][1]][0],1,y,s[root][1]);
update(s[root][1]),update(root);
}
inline void travel(int v)
{
down(v);
if(s[v][0]) travel(s[v][0]);
back[++back[0]]=v;
if(s[v][1]) travel(s[v][1]);
}
inline void delete_num(int x,int y)
{
splay(kth(root,x-1),0);
splay(kth(root,y+1),root);
travel(s[s[root][1]][0]);
s[s[root][1]][0]=0;
update(s[root][1]),update(root);
}
inline void flip(int l,int r)
{
splay(kth(root,l-1),0);
splay(kth(root,r+1),root);
reverse(s[s[root][1]][0]);
}
inline int get_max(int l,int r)
{
splay(kth(root,l-1),0);
splay(kth(root,r+1),root);
return mx[s[s[root][1]][0]];
}
inline void print(int v)
{
down(v);
if(s[v][0]) print(s[v][0]);
if(key[v]<inf) write(key[v]),putchar(' ');
if(s[v][1]) print(s[v][1]);
}
int main()
{
int n=read(),m=read();
a[1]=a[n+2]=-inf,c[0]=inf;
for(int i=2;i<=n+1;i++) a[i]=read();
build(root,1,n+2,0);
while(m--)
{
char ch=getchar();
while(ch!='X' && ch!='G' && ch!='V' && ch!='I' && ch!='D' && ch!='K') ch=getchar();
if(ch=='K')//MAKE-SAME
{
getchar(),getchar();
int x=read()+1,y=x+read()-1;
change(x,y,read());
}else
if(ch=='G')//GET-SUM
{
getchar(),getchar(),getchar();
int x=read()+1,y=x+read()-1;
write(get_sum(x,y)),putchar('\n');
}else
if(ch=='I')//INSERT
{
int x=read()+1,y=read();
for(int i=1;i<=y;i++) a[i]=read();
insert(x,y);
}else
if(ch=='D')//DELETE
{
int x=read()+1,y=x+read()-1;
delete_num(x,y);
}else
if(ch=='V')//REVERSE
{
int x=read()+1,y=x+read()-1;
flip(x,y);
}else
if(ch=='X')//MAX-SUM
{
write(get_max(2,size[root]-1)),putchar('\n');
scanf("\n");
}
}
return 0;
}
Code
//新打的,更快的,更短的
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
const int N=5e5+5,inf=1e9;
int root,tot;
int fa[N],s[N][2],key[N],size[N];
int pre[N],suf[N],sum[N],mx[N],c[N];
int a[N],back[N];
bool rev[N];
char st[10];
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline void write(int x)
{
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline int max(int x,int y)
{
return x>y?x:y;
}
inline bool pd(int x)
{
return x==s[fa[x]][1];
}
inline void update(int x)
{
sum[x]=sum[s[x][0]]+sum[s[x][1]]+key[x];
size[x]=size[s[x][0]]+size[s[x][1]]+1;
pre[x]=max(pre[s[x][0]],sum[s[x][0]]+key[x]+pre[s[x][1]]);
suf[x]=max(suf[s[x][1]],sum[s[x][1]]+key[x]+suf[s[x][0]]);
mx[x]=max(0,suf[s[x][0]])+key[x]+max(0,pre[s[x][1]]);
if(s[x][0]) mx[x]=max(mx[x],mx[s[x][0]]);
if(s[x][1]) mx[x]=max(mx[x],mx[s[x][1]]);
}
inline void newnode(int &v,int val,int p)
{
if(back[0]) v=back[back[0]--]; else v=++tot;
key[v]=sum[v]=mx[v]=val;
fa[v]=p,size[v]=1,c[v]=inf;
pre[v]=suf[v]=max(0,val);
s[v][0]=s[v][1]=rev[v]=0;
}
void build(int &v,int l,int r,int p)
{
if(l>r) return;
int mid=l+r>>1;
newnode(v,a[mid],p);
build(s[v][0],l,mid-1,v);
build(s[v][1],mid+1,r,v);
update(v);
}
inline void reverse(int x)
{
if(!x) return;
swap(s[x][0],s[x][1]);
swap(pre[x],suf[x]);
rev[x]^=1;
}
inline void modify(int x,int val)
{
if(!x) return;
sum[x]=size[x]*val,key[x]=c[x]=val;
if(val>0) pre[x]=suf[x]=mx[x]=sum[x]; else
pre[x]=suf[x]=0,mx[x]=val;
}
inline void down(int x)
{
if(rev[x])
{
reverse(s[x][0]),reverse(s[x][1]);
rev[x]=false;
}
if(c[x]<inf)
{
modify(s[x][0],c[x]),modify(s[x][1],c[x]);
c[x]=inf;
}
}
inline void rotate(int x)
{
down(x);
int y=fa[x],w=pd(x);
if(s[y][w]=s[x][w^1]) fa[s[y][w]]=y;
if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;
s[fa[y]=x][w^1]=y;
update(y);
}
inline void splay(int x,int k)
{
for(int y;(y=fa[x])^k;rotate(x))
if(fa[y]^k) rotate(pd(x)==pd(y)?y:x);
update(x);
if(!k) root=x;
}
int kth(int x,int k)
{
down(x);
if(size[s[x][0]]+1==k) return x;
if(size[s[x][0]]>=k) return kth(s[x][0],k);
return kth(s[x][1],k-size[s[x][0]]-1);
}
inline void get(int x,int y)
{
splay(kth(root,x-1),0);
splay(kth(root,y+1),root);
}
void travel(int x)
{
if(s[x][0]) travel(s[x][0]);
back[++back[0]]=x;
if(s[x][1]) travel(s[x][1]);
}
int main()
{
int n=read(),m=read();
a[1]=a[n+2]=inf;
for(int i=2;i<=n+1;i++) a[i]=read();
build(root,1,n+2,0);
while(m--)
{
scanf("%s",&st);
if(st[0]=='I')
{
int x=read()+1,y=read();
for(int i=1;i<=y;i++) a[i]=read();
splay(kth(root,x),0);
splay(kth(root,x+1),root);
build(s[s[root][1]][0],1,y,s[root][1]);
update(s[root][1]),update(root);
}else
if(st[0]=='D')
{
int x=read()+1,y=x+read()-1;
get(x,y);
travel(s[s[root][1]][0]);
s[s[root][1]][0]=0;
update(s[root][1]),update(root);
}else
if(st[0]=='R')
{
int x=read()+1,y=x+read()-1;
get(x,y);
reverse(s[s[root][1]][0]);
}else
if(st[0]=='G')
{
int x=read()+1,y=x+read()-1;
get(x,y);
write(sum[s[s[root][1]][0]]),putchar('\n');
}else
if(st[2]=='K')
{
int x=read()+1,y=x+read()-1,z=read();
get(x,y);
modify(s[s[root][1]][0],z);
}else
{
get(2,size[root]-1);
write(mx[s[s[root][1]][0]]),putchar('\n');
}
}
return 0;
}