这题貌似比operation还要恶心一点。。。
为了练习splay硬着头皮写的,虽然现在AC了但我还是完全没有信心能够在考场上写出来,细节太多,下面进入正题。
1、最大序列和的询问,仿照线段树,需要维护Max,Maxl,Maxr,sum这几个量,在上传的时候更新。
2、由于内存限制,需要回收内存的操作,就是将下标回收进入一个数组,具体见代码。
3、标记要向下传递两层。(Ps:这个我也不知道为什么,我在这里卡了很久)
4、两个虚拟节点以及Max的初始值为-inf
5、不要将lazy标记与lazy标记的值合并,多开一个bool来标记
这道题的trick暂时就想到这些,至于其他的操作就与一般的splay维护数列的题无异了。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#define keyTree ch[ ch[root][1] ][0]
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 550000 + 10;
const int bh = maxn - 10;
struct SplayTree
{
int ch[maxn][2],pre[maxn],num[maxn];
int ss[maxn],que[maxn];
int val[maxn],sum[maxn],sz[maxn];
int Maxl[maxn],Maxr[maxn],Max[maxn];
int lazy[maxn];
bool reserve[maxn],same[maxn];
int root,top1,top2;
int max(int a,int b)
{
return a > b ? a : b;
}
int max(int a,int b,int c)
{
return max(max(a,b),c);
}
void swap(int &a,int &b)
{
int t = a;a = b;b = t;
}
void push_up(int x)
{
sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;
sum[x] = val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];
Maxl[x] = max(Maxl[ ch[x][0] ],sum[ ch[x][0] ] + val[x] + max(0,Maxl[ ch[x][1] ]));
Maxr[x] = max(Maxr[ ch[x][1] ],sum[ ch[x][1] ] + val[x] + max(0,Maxr[ ch[x][0] ]));
Max[x] = max(Max[ ch[x][0] ],Max[ ch[x][1] ],val[x]);
Max[x] = max(Max[x],max(Maxr[ ch[x][0] ],Maxl[ ch[x][1] ]) + val[x]);
Max[x] = max(Max[x],Maxr[ ch[x][0] ] + val[x] + Maxl[ ch[x][1] ]);
}
void deal1(int x,int tmp)
{
same[x] = true,lazy[x] = tmp;
sum[x] = tmp * sz[x];
Max[x] = Maxl[x] = Maxr[x] = max(sum[x],tmp);
}
void deal2(int x)
{
reserve[x] = !reserve[x];
swap(Maxl[x],Maxr[x]);
}
void push_down(int x)
{
if(same[x])
{
val[x] = lazy[x];
if(ch[x][0])deal1(ch[x][0],lazy[x]);
if(ch[x][1])deal1(ch[x][1],lazy[x]);
same[x] = reserve[x] = false;
}
if(reserve[x])
{
swap(ch[x][0],ch[x][1]);
swap(Maxl[x],Maxr[x]);
if(ch[x][0])deal2(ch[x][0]);
if(ch[x][1])deal2(ch[x][1]);
reserve[x] = false;
}
}
void Rotate(int x,int f)
{
int y = pre[x];
push_down(y);push_down(x);
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(pre[x])ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
ch[x][f] = y;
pre[y] = x;
push_up(y);
}
void Splay(int x,int goal)
{
push_down(x);
while(pre[x] != goal)
{
if(pre[pre[x]] == goal)Rotate(x, ch[pre[x]][0] == x);
else
{
int y = pre[x],z = pre[y];
int f = (ch[z][0] == y);
if(ch[y][f] == x)Rotate(x,!f),Rotate(x,f);
else Rotate(y,f),Rotate(x,f);
}
}
push_up(x);
if(goal == 0)root = x;
}
void RotateTo(int k,int goal)
{
int x = root;
push_down(x);
while(sz[ ch[x][0] ] != k)
{
if(k < sz[ ch[x][0] ])x = ch[x][0];
else
{
k -= (sz[ ch[x][0] ] + 1);
x = ch[x][1];
}
push_down(x);
}
Splay(x,goal);
}
void Newnode(int &x,int c)
{
if(top2)x = ss[--top2];
else x = ++top1;
ch[x][0] = ch[x][1] = pre[x] = 0;
sz[x] = 1;
lazy[x] = 0;
reserve[x] = same[x] = false;
val[x] = sum[x] = c;
Maxl[x] = Maxr[x] = Max[x] = c;
}
void makeTree(int &x,int l,int r,int f,int *p)
{
if(l > r)return;
int m = (l + r) >> 1;
Newnode(x,p[m]);
makeTree(ch[x][0],l , m - 1,x,p);
makeTree(ch[x][1],m + 1 , r,x,p);
pre[x] = f;
push_up(x);
}
void erase(int x)
{
int father = pre[x];
int head = 0,tail = 0;
for(que[tail++] = x;head < tail;head ++)
{
ss[top2++] = que[head];
if(ch[ que[head] ][0])que[tail++] = ch[ que[head] ][0];
if(ch[ que[head] ][1])que[tail++] = ch[ que[head] ][1];
}
ch[ father ][ ch[father][1] == x ] = 0;
push_up(father);
}
void init(int n)
{
memset(Max,~0x3f,sizeof(Max));
ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
root = top1 = top2 = 0;
Newnode(root,-inf);
Newnode(ch[root][1],-inf);
pre[ch[root][1]] = root;
sz[root] = 2;
for(int i = 1;i <= n;i++)scanf("%d",&num[i]);
makeTree(keyTree,1,n,ch[root][1],num);
push_up(ch[root][1]);
push_up(root);
}
void ins(int pos,int tot,int *tmp)
{
RotateTo(pos,0);RotateTo(pos + 1,root);
makeTree(keyTree,1,tot,ch[root][1],tmp);
Splay(keyTree,0);
}
void update(int pos,int tot,int c)
{
RotateTo(pos - 1,0);RotateTo(pos + tot,root);
deal1(keyTree,c);
Splay(keyTree,0);
}
void del(int pos,int tot)
{
RotateTo(pos - 1,0);RotateTo(pos + tot,root);
erase(keyTree);
Splay(ch[root][1],0);
}
void res(int pos,int tot)
{
RotateTo(pos - 1,0);RotateTo(pos + tot,root);
reserve[ keyTree ] = !reserve[ keyTree ];
Splay(keyTree,0);
}
int getsum(int pos,int tot)
{
RotateTo(pos - 1,0);RotateTo(pos + tot,root);
return sum[ keyTree ];
}
int query(){return Max[root];}
}Spt;
int n,m;
int tmp[maxn];
void init()
{
freopen("bzoj1500.in","r",stdin);
freopen("bzoj1500.out","w",stdout);
}
void readdata()
{
scanf("%d%d",&n,&m);
Spt.init(n);
for(int i = 1;i <= m;i++)
{
char op[10];
int pos,tot;
scanf("%s",op);
if(!strcmp(op,"MAX-SUM"))printf("%d\n",Spt.query());
else
{
scanf("%d%d",&pos,&tot);
if(!strcmp(op,"INSERT"))
{
for(int j = 1;j <= tot;j++)scanf("%d",&tmp[j]);
Spt.ins(pos,tot,tmp);
}
if(!strcmp(op,"DELETE"))Spt.del(pos,tot);
if(!strcmp(op,"MAKE-SAME"))
{
int c;
scanf("%d",&c);
Spt.update(pos,tot,c);
}
if(!strcmp(op,"REVERSE"))Spt.res(pos,tot);
if(!strcmp(op,"GET-SUM"))printf("%d\n",Spt.getsum(pos,tot));
}
}
}
int main()
{
init();
readdata();
return 0;
}