Description
维护一个数列,支持6种操作。
1:插入 在第pos个数后面插入tot个数
2:删除 删除第pos个数开始的tot个数
3:修改 将第pos个数开始的tot个数统一改成c
4:翻转 将第pos个数开始的tot个数翻转
5:求和 计算第pos个数开始的tot个数的和
6:最大和子序列 求这个序列的最大和子序列
100%的数据中,任何时刻数列中最多含有500 000个数。
100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
100%的数据中,操作数≤2*10^4,插入的数字总数不超过4 *10^7个.
Solution
看到翻转神马的,splay直接上。
考验码力的时候到了。
某神犇:把这道题拎出来,在一个小时内切掉,你以后splay都可以随脑打了。
我只不过打了2.5h而已(带垃圾回收)。。。(果然splay还是无法像segmenttree一样)
上bzoj交了一发,5504ms,(⊙v⊙)嗯,看看排第几?
!!!第一那个1316ms是怎么回事(⊙_⊙?)
我在哪?
。。。。
。。。。
。。。。
。。。。
620,好数字~(>_<)~
图样图森破
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 500005
using namespace std;
const int Mx=1005;
int t[N][2],f[N],a[N],d[N],stack[N],rev[N],same[N],key[N],n,m,z,root,tot,pos,cnt;
char s[25];
struct note{
int son[2],lmax,rmax,sum,max,size;
}tr[N];
int newnode(int x) {
int id;
if (d[0]) id=d[d[0]--];else id=++cnt;tr[id].size=1;same[id]=Mx;
key[id]=tr[id].sum=tr[id].max=x;tr[id].lmax=tr[id].rmax=max(x,0);
rev[id]=f[id]=t[id][0]=t[id][1]=0;
return id;
}
void updata(int x) {
if (!x) return;
int l=t[x][0],r=t[x][1];
tr[x].size=tr[l].size+tr[r].size+1;
tr[x].sum=tr[l].sum+tr[r].sum+key[x];
tr[x].lmax=max(tr[l].lmax,tr[l].sum+key[x]+tr[r].lmax);
tr[x].rmax=max(tr[r].rmax,tr[r].sum+key[x]+tr[l].rmax);
tr[x].max=max(tr[l].max,max(tr[r].max,tr[l].rmax+key[x]+tr[r].lmax));
}
void makesame(int x,int y) {
if (!x) return;
tr[x].sum=y*tr[x].size;
key[x]=y;same[x]=y;
if (y>0) tr[x].lmax=tr[x].rmax=tr[x].max=tr[x].sum;
else tr[x].lmax=tr[x].rmax=0,tr[x].max=y;
}
void reverse(int x) {
if (!x) return;
swap(t[x][0],t[x][1]);
swap(tr[x].lmax,tr[x].rmax);
rev[x]^=1;
}
void down(int x) {
if (!x) return;
if (same[x]!=Mx) {
makesame(t[x][0],same[x]);
makesame(t[x][1],same[x]);
same[x]=Mx;
}
if (rev[x]) {
reverse(t[x][0]);
reverse(t[x][1]);
rev[x]=0;
}
}
void remove(int x,int y) {
do {
stack[++stack[0]]=x;x=f[x];
} while (x!=y);
while (stack[0]) down(stack[stack[0]--]);
}
int build(int l,int r,int fa) {
if (l>r) return 0;
int m=(l+r)/2,x=newnode(a[m]);
f[x]=fa;
if (l==r) return x;
t[x][0]=build(l,m-1,x);
t[x][1]=build(m+1,r,x);
updata(x);return x;
}
int get_id(int x,int id) {
down(x);
if (tr[t[x][0]].size+1==id) return x;
if (tr[t[x][0]].size+1>id) return get_id(t[x][0],id);
else return get_id(t[x][1],id-tr[t[x][0]].size-1);
}
int son(int x) {
if (x==t[f[x]][0]) return 0;else return 1;
}
void rotate(int x) {
int y=f[x],z=son(x);f[x]=f[y];
if (f[x]) t[f[x]][son(y)]=x;
if (t[x][1-z]) f[t[x][1-z]]=y;
f[y]=x;t[y][z]=t[x][1-z];t[x][1-z]=y;
updata(y);updata(x);
}
void splay(int x,int y) {
if (x==y) return;
remove(x,y);
while (f[x]!=y) {
if (f[f[x]]!=y)
if (son(x)==son(f[x])) rotate(f[x]);
else rotate(x);
rotate(x);
}
if (!y) root=x;
}
void del(int x) {
if (!x) return;d[++d[0]]=x;
del(t[x][0]);del(t[x][1]);
}
int main() {
scanf("%d%d",&n,&m);tr[0].max=-0x7fffffff;
fo(i,1,n) scanf("%d",&a[i]);
root=build(0,n+1,0);
for(;m;m--) {
scanf("%s",s);
if (s[0]=='I') {
scanf("%d%d",&pos,&tot);pos++;
fo(i,1,tot) scanf("%d",&a[i]);
int x=get_id(root,pos);splay(x,0);
int y=get_id(root,pos+1);splay(y,x);
t[y][0]=build(1,tot,y);updata(y);updata(x);
}
if (s[0]=='D') {
scanf("%d%d",&pos,&tot);pos++;
int x=get_id(root,pos-1);splay(x,0);
int y=get_id(root,pos+tot);splay(y,x);
del(t[y][0]);t[y][0]=0;updata(y);updata(x);
}
if (s[2]=='K') {
scanf("%d%d%d",&pos,&tot,&z);pos++;
int x=get_id(root,pos-1);splay(x,0);
int y=get_id(root,pos+tot);splay(y,x);
makesame(t[y][0],z);updata(y);updata(x);
}
if (s[0]=='R') {
scanf("%d%d",&pos,&tot);pos++;
int x=get_id(root,pos-1);splay(x,0);
int y=get_id(root,pos+tot);splay(y,x);
reverse(t[y][0]);updata(y);updata(x);
}
if (s[0]=='G') {
scanf("%d%d",&pos,&tot);pos++;
int x=get_id(root,pos-1);splay(x,0);
int y=get_id(root,pos+tot);splay(y,x);
printf("%d\n",tr[t[y][0]].sum);
}
if (s[2]=='X') {
int x=get_id(root,1);splay(x,0);
int y=get_id(root,tr[root].size);splay(y,x);
printf("%d\n",tr[t[y][0]].max);
}
}
}