在这里存一波splay模板题,啃起来有点难。。
Description
请写一个程序,要求维护一个数列,支持以下 6 种操作:
请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
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
HINT
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include <sstream>
#define inf 800000000
#define ll long long
#define mod 1000000007
using namespace std;
const int maxn=500000;
int n,m,i,nnode=0,rest=0,root=0,root1,pos,tot,k,q[maxn],c[maxn][2],size[maxn],pre[maxn],num[maxn],maxsum[maxn],maxpre[maxn],maxpos[maxn],same[maxn],rev[maxn],sum[4000005],s[maxn];
char str[10];
void update(int x)
{
size[x]=size[c[x][0]]+size[c[x][1]]+1;sum[x]=sum[c[x][0]]+sum[c[x][1]]+num[x];
maxsum[x]=max(max(maxsum[c[x][0]],maxsum[c[x][1]]),maxpos[c[x][0]]+num[x]+maxpre[c[x][1]]);
maxpre[x]=max(sum[c[x][0]]+maxpre[c[x][1]]+num[x],maxpre[c[x][0]]);maxpos[x]=max(sum[c[x][1]]+maxpos[c[x][0]]+num[x],maxpos[c[x][1]]);
}
void marksame(int x,int c)
{
same[x]=c;
if (c==1001) c=0;
num[x]=c;sum[x]=size[x]*c;
if (c>=0) maxsum[x]=maxpre[x]=maxpos[x]=size[x]*c; else maxpre[x]=maxpos[x]=0,maxsum[x]=c;
}
void markrev(int x)
{
swap(c[x][0],c[x][1]);
swap(maxpre[x],maxpos[x]);
rev[x]^=1;
}
void down(int x)
{
if (same[x])
{
if (c[x][0]) marksame(c[x][0],same[x]); if (c[x][1]) marksame(c[x][1],same[x]);
same[x]=0;
}
if (rev[x])
{
if (c[x][0]) markrev(c[x][0]);if (c[x][1]) markrev(c[x][1]);
rev[x]=0;
}
}
void newnode(int &x,int fa,int k)
{
if (rest) x=s[rest--];else x=++nnode;
pre[x]=fa;num[x]=k; size[x]=1;
c[x][0]=c[x][1]=same[x]=rev[x]=0;
sum[x]=maxsum[x]=k;
maxpre[x]=maxpos[x]=max(k,0);
}
void rot(int x,int kind)
{
int y=pre[x];int z=pre[y];down(x);
c[y][!kind]=c[x][kind];pre[c[x][kind]]=y;
c[x][kind]=y;pre[y]=x;
pre[x]=z;if (z) c[z][c[z][1]==y]=x;
update(y);update(x);if (z) update(z);
}
void splay(int x,int goal)
{
int y,z,kind;
while (pre[x]!=goal)
{
y=pre[x];down(y);
if (pre[y]==goal) rot(x,c[y][0]==x);
else
{
z=pre[y];down(z);kind=c[z][0]==y;
if (c[y][!kind]==x) rot(y,kind);else rot(x,!kind);
rot(x,kind);
}
}
if (goal==0) root=x;
}
int findkth(int x,int k)//加处理
{
down(x);
if (size[c[x][0]]>=k) return findkth(c[x][0],k);
if (k==size[c[x][0]]+1) return x;
if (k>size[c[x][0]]+1) return findkth(c[x][1],k-size[c[x][0]]-1);
}
void build(int &x,int fa,int l,int r)
{
if (l>r) return;
int mid=(l+r)/2;
newnode(x,fa,q[mid]);
if (l==r) return;
build(c[x][0],x,l,mid-1);build(c[x][1],x,mid+1,r);
update(x);
}
void insert(int pos,int tot)
{
int i;
for (i=1;i<=tot;i++)
scanf("%d",&q[i]);
build(root1,0,1,tot);
splay(findkth(root,pos+1),0);
splay(findkth(root,pos+2),root);
c[c[root][1]][0]=root1;pre[root1]=c[root][1];
update(c[root][1]);update(root);
}
void erase(int x)
{
if (!x) return;
s[++rest]=x;
erase(c[x][0]);erase(c[x][1]);
}
void deleted(int pos,int tot)
{
splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
erase(c[c[root][1]][0]);
c[c[root][1]][0]=0;
update(c[root][1]);update(root);
}
void makesame(int pos,int tot,int k)
{
if (k==0) k=1001;
splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
marksame(c[c[root][1]][0],k);
update(c[root][1]);update(root);
}
void markrev(int pos,int tot)
{
splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
markrev(c[c[root][1]][0]);
update(c[root][1]);update(root);
}
int getsum(int pos,int tot)
{
splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
return sum[c[c[root][1]][0]];
}
void print(int x)
{
if (c[x][0]) print(c[x][0]);
printf("%d->num:%d,fa:%d,lc:%d,rc:%d,size:%d,sum:%d,maxpre:%d,maxpos:%d,maxsum:%d,same:%d,rev:%d\n",x,num[x],pre[x],c[x][0],c[x][1],size[x],sum[x],maxpre[x],maxpos[x],maxsum[x],same[x],rev[x]);
if (c[x][1])print(c[x][1]);
}
int main()
{
//freopen("shulie.in","r",stdin);
//freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
newnode(root,0,-inf);newnode(c[root][1],root,-inf);
insert(0,n);
size[0]=pre[0]=same[0]=rev[0]=num[0]=sum[0]=maxpre[0]=maxpos[0]=0;maxsum[0]=-inf;
for (i=1;i<=m;i++)
{
scanf("%s",&str);
if (str[2]!='X') scanf("%d%d",&pos,&tot); else printf("%d\n",maxsum[root]);
if (str[0]=='I') insert(pos,tot);
if (str[0]=='D') deleted(pos,tot);
if (str[0]=='M'&&str[2]=='K') scanf("%d",&k),makesame(pos,tot,k);
if (str[0]=='R') markrev(pos,tot);
if (str[0]=='G') printf("%d\n",getsum(pos,tot));
}
}