splay鼻祖级的题目??(雾。。
Insert:把第pos个数(有哨兵节点)转到root,把第pos+1个数转到root的右儿子,然后对c[]建树然后把这棵树插到root右儿子的左儿子处
Delete:把第pos个数转到root,把第pos+tot+1个数转到root右儿子,删掉root右儿子的左儿子(变成0);注意回收空间,所以还要把这棵子树遍历一边。
Make-Same:像上面那样转,对root右儿子的左儿子-> setv=c
Reverse:转,对root右儿子的左儿子->rz^=1;
Get-sum:转,printf("%d", tr[x].sum);
Max-sum:printf("%d", tr[root].mx);
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
样例原始的那颗splay:
蓝色是点在数组tr中的编号,紫色是子树的大小
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define MAXN 500010
#define INF 2000//不可以太大,否则几个加起来就爆炸了
#define u tr[x]
#define lc tr[x].ch[0]
#define rc tr[x].ch[1]
#define LC tr[lc]
#define RC tr[rc]
struct node{
int ch[2],f,v,sz,mx,lm,rm,sum,sv;
bool rv;
void set(int x)
{
ch[0]=ch[1]=f=sz=mx=lm=rm=sum=0;v=x;
sv=INF;rv=0;
}
}tr[MAXN];
char s[15];
int a[MAXN],id[MAXN],n,m,x,t,root,tot,c;
void PD(int x)
{
if (!x) return ;
if (u.sv!=INF)
{
LC.sv=RC.sv=u.v=u.sv;//!!вЊгаu.v
u.sum=u.sv*u.sz;
u.mx=max(u.sv,u.sum);
u.lm=u.rm=max(0,u.mx);
u.sv=INF;
}
if (u.rv)
{
LC.rv^=1;RC.rv^=1;
swap(lc,rc);swap(u.lm,u.rm);
u.rv=0;
}
}
void updata(int x)
{
if (!x) return ;
PD(x);PD(lc);PD(rc);
u.sz=LC.sz+RC.sz+1;
u.sum=LC.sum+RC.sum+u.v;
u.lm=max(LC.lm,LC.sum+u.v+max(0,RC.lm));
u.rm=max(RC.rm,RC.sum+u.v+max(0,LC.rm));
u.mx=max(0,LC.rm)+u.v+max(0,RC.lm);
u.mx=max(u.mx,max(LC.mx,RC.mx));
}
int build(int l,int r)
{
if (l>r) return 0;
int x=id[++tot];
int mid=(l+r) >> 1;
u.set(a[mid]);
lc=build(l,mid-1);rc=build(mid+1,r);
LC.f=RC.f=x;tr[x].sv=INF;
updata(x);
return x;
}
void SC(int x,int y,bool z)
{
tr[y].f=x;
if (x) tr[x].ch[z]=y;
}
inline bool d(int x) {return tr[tr[x].f].ch[1]==x;}
void rot(int x)
{
int y=u.f,z=tr[y].f,t=d(x);
SC(z,x,d(y));SC(y,tr[x].ch[!t],t);SC(x,y,!t);
updata(y);
}
void splay(int x,int f)
{
PD(x);
if (!f) root=x;
while (tr[x].f!=f)
{
PD(tr[x].f);PD(x);
if (tr[tr[x].f].f==f) {rot(x);break;}
if (d(x)==d(tr[x].f)) {rot(tr[x].f);rot(x);} else {rot(x);rot(x);}
}
updata(x);
}
int find(int x,int y)
{
PD(x);
if (LC.sz+1<y) return find(rc,y-LC.sz-1);
else if (LC.sz+1==y) return x;
else return find(lc,y);
}
int get(int x,int y)
{
x++;y++;
int x1=find(root,x);int y1=find(root,y);
splay(x1,0);splay(y1,x1);
updata(root);
return y1;
}
void del(int x)
{
if (!x) return ;
id[tot--]=x;
del(lc);del(rc);
}
int main()
{
scanf("%d%d", &n, &m);
for (int i=1;i<MAXN;i++) id[i]=i;
for (int i=1;i<=n;i++) scanf("%d", &a[i]);
a[0]=a[n+1]=-INF;tr[0].mx=-INF;
root=build(0,n+1);
for (int i=1;i<=m;i++)
{
scanf("%s", s);
if (s[0]=='M' && s[2]=='X')
{updata(root);printf("%d\n", tr[root].mx);}
else
{
scanf("%d%d", &x, &t);
if (s[0]=='I')
{
x=get(x,x+1);
for (int j=1;j<=t;j++) scanf("%d", &a[j]);
SC(x,build(1,t),0);updata(x);updata(root);
}
if (s[0]=='D')
{
x=get(x-1,x+t);
del(lc);lc=0;
updata(x);updata(root);
}
if (s[0]=='M' && s[2]=='K')
{
scanf("%d", &c);
x=get(x-1,x+t);
LC.sv=c;updata(lc);updata(x);updata(root);//!!updata(lc);
}
if (s[0]=='R')
{
x=get(x-1,x+t);
LC.rv^=1;updata(lc);updata(x);updata(root);//!!updata(lc);
}
if (s[0]=='G')
{
x=get(x-1,x+t);
printf("%d\n", LC.sum);
}
}
}
return 0;
}