经典的题目,包含了Splay常见的操作:区间最值,区间求和,区间翻转,区间改值等。
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <map>
#include <cmath>
#include <stack>
#include <algorithm>
#define Value ch[ch[root][1]][0]
using namespace std;
typedef long long LL ;
const int maxn=500005;
const int INF=0x3f3f3f3f;
int n;
int a[maxn];
struct Splay
{
int tot1,tot2,root;
int s[maxn];
int sum[maxn],pre[maxn],ch[maxn][2],val[maxn];
int size[maxn],mx[maxn],lx[maxn],rx[maxn],rev[maxn],same[maxn];
void newNode(int &x,int father,int v)
{
if(tot2) x=s[tot2--];
else x=++tot1;
ch[x][0]=ch[x][1]=0;
rev[x]=same[x]=0;
pre[x]=father;
size[x]=1;
val[x]=sum[x]=v;
lx[x]=rx[x]=mx[x]=v;
}
void push_up(int x)
{
int ls=ch[x][0],rs=ch[x][1];
size[x]=size[ls]+size[rs]+1;
sum[x]=sum[ls]+sum[rs]+val[x];
lx[x]=max(lx[ls],sum[ls]+val[x]+max(0,lx[rs]));
rx[x]=max(rx[rs],sum[rs]+val[x]+max(0,rx[ls]));
mx[x]=max(0,rx[ls])+val[x]+max(lx[rs],0);
mx[x]=max(mx[x],max(mx[ls],mx[rs]));
}
void do_rev(int x)
{
if(!x) return ;
swap(ch[x][0],ch[x][1]);
swap(lx[x],rx[x]);
rev[x]^=1;
}
void do_same(int x,int v)
{
if(!x) return ;
val[x]=v;
sum[x]=size[x]*v;
lx[x]=rx[x]=mx[x]=max(v,sum[x]);
same[x]=1;
}
void do_erase(int x)
{
if(!x) return ;
s[++tot2]=x;
do_erase(ch[x][0]);
do_erase(ch[x][1]);
}
void push_down(int x)
{
if(same[x])
{
same[x]=0;
do_same(ch[x][0],val[x]);
do_same(ch[x][1],val[x]);
}
if(rev[x])
{
rev[x]=0;
do_rev(ch[x][0]);
do_rev(ch[x][1]);
}
}
void rotate(int x,int kind)
{
int y=pre[x];
push_down(y);
push_down(x);
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
push_up(y);
}
void adjust(int x,int g)
{
while(pre[x]!=g)
{
if(pre[pre[x]]==g)
{
rotate(x,ch[pre[x]][0]==x);
}
else
{
int y=pre[x];
int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x)
{
rotate(x,!kind);
rotate(x,kind);
}
else
{
rotate(y,kind);
rotate(x,kind);
}
}
}
push_up(x);
if(g==0)
root=x;
}
int getKth(int x,int k)
{
push_down(x);
int t=size[ch[x][0]]+1;
if(t==k)
return x;
else if(k<t)
return getKth(ch[x][0],k);
else
return getKth(ch[x][1],k-t);
}
void update_erase(int l,int r)
{
adjust(getKth(root,l),0);
adjust(getKth(root,l+r+1),root);
do_erase(Value);
pre[Value]=0;
Value=0;
push_up(ch[root][1]);
push_up(root);
}
void update_rev(int l,int r)
{
adjust(getKth(root,l),0);
adjust(getKth(root,l+r+1),root);
do_rev(Value);
push_up(ch[root][1]);
push_up(root);
}
void update_same(int l,int r,int v)
{
adjust(getKth(root,l),0);
adjust(getKth(root,l+r+1),root);
do_same(Value,v);
push_up(ch[root][1]);
push_up(root);
}
void update_insert(int pos,int nn)
{
adjust(getKth(root,pos+1),0);
adjust(getKth(root,pos+2),root);
for(int i=0; i<nn; ++i)
scanf("%d",&a[i]);
build(Value,0,nn-1,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
int get_Sum(int l,int r)
{
adjust(getKth(root,l),0);
adjust(getKth(root,l+r+1),root);
return sum[Value];
}
int get_Max(int l,int r)
{
adjust(getKth(root,l),0);
adjust(getKth(root,l+r+1),root);
return mx[Value];
}
void init()
{
root = tot1 = tot2 = 0;
ch[root][0] = ch[root][1] = size[root] = pre[root] = 0;
same[root] = rev[root] = sum[root] = val[root] = 0;
lx[root] = rx[root] = mx[root] = -INF;
newNode(root,0,-1);
newNode(ch[root][1],root,-1);
for(int i=0; i<n; ++i)
scanf("%d",&a[i]);
build(Value,0,n-1,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
void build(int &x,int l,int r,int father)
{
if(l>r) return ;
int m=l+(r-l)/2;
newNode(x,father,a[m]);
build(ch[x][0],l,m-1,x);
build(ch[x][1],m+1,r,x);
push_up(x);
}
};
Splay tree;
int main()
{
int m;
scanf("%d%d",&n,&m);
tree.init();
while(m--)
{
char str[20];
scanf("%s",str);
if(strcmp(str,"GET-SUM")==0)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",tree.get_Sum(x,y));
}
else if(strcmp(str,"MAX-SUM")==0)
{
int x,y;
printf("%d\n",tree.get_Max(1,tree.size[tree.root]-2));
}
else if(strcmp(str,"INSERT")==0)
{
int x,y;
scanf("%d%d",&x,&y);
tree.update_insert(x,y);
}
else if(strcmp(str,"DELETE")==0)
{
int x,y;
scanf("%d%d",&x,&y);
tree.update_erase(x,y);
}
else if(strcmp(str,"MAKE-SAME")==0)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
tree.update_same(x,y,z);
}
else if(strcmp(str,"REVERSE")==0)
{
int x,y;
scanf("%d%d",&x,&y);
tree.update_rev(x,y);
}
}
return 0;
}