Time:2016.05.12
Author:xiaoyimi
转载注明出处谢谢
传送门1
传送门2
思路:
我的天啊!
Splay大板子!
调了好久啊!
这里的Splay没有判断的key值,换一种说法,这不是一个严格的二叉查找树,只是借用了Splay的实现形式,或者说我们可以理解成key值就是它的插入顺序……
1.插入
把pos代表的节点转到根,pos+1代表的节点转到根下面(即pos的右子树),然后往pos+1左子树上插就可以了
2.删除
pos-1代表的节点转到根,pos+tot代表的节点转到根的右子树,那么pos+tot代表的节点的左子树就是我们要删除的全部节点
3.修改
和删除操作类似,这里不是删除,而是在pos+tot的左子树上类似线段树那样的打上数字标记
4.翻转
和删除、修改操作类似,打翻转标记,同时这里的翻转标记代表其所在节点的左右儿子已交换,下传时也要让左右儿子的子树交换,以此类推
5.求和
对于某一节点x,其sum为左儿子+右儿子+自身,所以直接像2,3,4操作那样转一下,输出sum即可
6.求最大连续子列
(这里的最大连续子列不能是空)
像线段树一样的记录当前节点的总最大和,左端所在最大和,右端所在最大和,上传时要仔细想想。这里我被0的问题纠结了好久,所以又维护了一个单点最大值,那么如果所求序列里全是负数,输出的就是一个最大的负数
注意:
坑点无穷!
首先你必须开一个内存池存编号啥的,不管是指针还是数组,不然插入的数
4∗106
不回收,64MB内存早就炸飞了
插入时把插入的序列弄成一颗平衡树再插进去,不然插入一条链是会T的
翻转区间时左右子树交换,左端最大和、右端最大和也要交换
平衡树中加两个哨兵节点,值为0,能避免很多讨论情况(比如找第k大再旋转什么的)
总最大和长度不能为0,但左、右端可以为0
每次Splay,rorate啥的都要上传下放标记……吗
当你觉得你的程序没什么问题但就是WA or TLE的时候,那就来一发紧张刺激的Splay操作
代码:
#include<bits/stdc++.h>
#define M 500005
using namespace std;
int n,m,tot,root;
int stacks[M],fa[M],son[M][2],siz[M],sum[M],pre[M],sub[M],data[M],lazy[M],maxn[M],mx[M],reads[M];
bool rev[M];
char s[11];
queue<int>q;
int in()
{
char ch=getchar();int t=0,f=1;
while (ch>'9'||ch<'0')
{
if (ch=='-') f=-1;
else if (f==-1) f=1;
ch=getchar();
}
while (ch>='0'&&ch<='9') t=(t<<3)+(t<<1)+ch-48,ch=getchar();
return f*t;
}
void ct(int x)
{
int ls=son[x][0],rs=son[x][1];
siz[x]=1+siz[ls]+siz[rs];
sum[x]=data[x]+sum[ls]+sum[rs];
mx[x]=max(max(mx[ls],mx[rs]),data[x]);
maxn[x]=max(max(maxn[ls],maxn[rs]),data[x]+pre[rs]+sub[ls]);
pre[x]=max(pre[ls],sum[ls]+data[x]+pre[rs]);
sub[x]=max(sub[rs],sum[rs]+data[x]+sub[ls]);
}
void rever(int x){swap(son[x][0],son[x][1]);swap(pre[x],sub[x]);}
void pushdown(int x)
{
if (!rev[x]&&lazy[x]==-1001) return;
if (rev[x])
rev[son[x][0]]^=1,
rev[son[x][1]]^=1,
rever(son[x][0]),rever(son[x][1]),
rev[x]=0;
if (lazy[x]!=-1001)
lazy[son[x][0]]=lazy[x],
sum[son[x][0]]=lazy[x]*siz[son[x][0]],
maxn[son[x][0]]=max(sum[son[x][0]],lazy[x]),
sub[son[x][0]]=pre[son[x][0]]=max(0,sum[son[x][0]]),
data[son[x][0]]=data[son[x][1]]=lazy[x],
mx[son[x][0]]=mx[son[x][1]]=lazy[x],
lazy[son[x][1]]=lazy[x],
sum[son[x][1]]=lazy[x]*siz[son[x][1]],
maxn[son[x][1]]=max(sum[son[x][1]],lazy[x]),
sub[son[x][1]]=pre[son[x][1]]=max(0,sum[son[x][1]]),
lazy[x]=-1001;
}
int make(int x)
{
int now=stacks[stacks[0]--];
maxn[now]=mx[now]=data[now]=x;
lazy[now]=-1001;rev[now]=0;
son[now][0]=son[now][1]=0;
return now;
}
void rorate(int x,bool mk)
{
int y=fa[x];
pushdown(y);pushdown(x);
fa[son[x][mk]]=y;son[y][!mk]=son[x][mk];
fa[x]=fa[y];
if (fa[y])
{
if (son[fa[y]][0]==y) son[fa[y]][0]=x;
else son[fa[y]][1]=x;
}
fa[y]=x;son[x][mk]=y;
ct(y);ct(x);
}
void splay(int x,int goal)
{
int y;
while (fa[x]!=goal)
{
y=fa[x];
if (fa[y]==goal)
{
if (son[y][0]==x) rorate(x,1);
else rorate(x,0);
}
else if (son[fa[y]][0]==y)
{
if (son[y][0]==x) rorate(y,1);
else rorate(x,0);
rorate(x,1);
}
else
{
if (son[y][1]==x) rorate(y,0);
else rorate(x,1);
rorate(x,0);
}
}
if (!goal) root=x;
}
int Kth(int k)
{
if (!k) return 0;
int x=root;
while (x)
{
pushdown(x);
if (siz[son[x][0]]+1==k) return x;
if (siz[son[x][0]]+1>k) x=son[x][0];
else k-=siz[son[x][0]]+1,x=son[x][1];
}
}
int build(int begin,int end)
{
if (begin>end) return 0;
int mid=begin+end>>1;
int now=make(reads[mid]),ls=build(begin,mid-1),rs=build(mid+1,end);
son[now][0]=ls;son[now][1]=rs;
fa[ls]=fa[rs]=now;
ct(now);
return now;
}
main()
{
for (int i=1;i<=M-3;i++) stacks[i]=M-3-i+1,lazy[i]=-1001;
stacks[0]=M-3;
n=in();m=in();
reads[1]=0;reads[n+2]=0;
for (int i=2;i<=n+1;i++) reads[i]=in();
int pos,x,c,mid=(n+3)>>1;
root=build(1,n+2);
tot=n+2;
while (m--)
{
s[0]=getchar();
int t=0;
while (s[0]<'A'||s[0]>'Z')s[0]=getchar();
while ((s[t]>='A'&&s[t]<='Z')||s[t]=='-') s[++t]=getchar();
if (s[0]=='I')
{
pos=in()+1;x=in();
tot+=x;
splay(Kth(pos),0);
splay(Kth(pos+1),root);
for (int i=1;i<=x;i++) reads[i]=in();
pos=build(1,x);
fa[pos]=son[root][1];
son[son[root][1]][0]=pos;
ct(son[root][1]);ct(root);
}
else if (s[0]=='D')
{
pos=in()+1;x=in();
tot-=x;
splay(Kth(pos-1),0);
splay(Kth(pos+x),root);
pos=son[root][1];
if (son[pos][0]) q.push(son[pos][0]),son[pos][0]=0;
ct(pos);ct(root);
for (;!q.empty();q.pop())
{
stacks[++stacks[0]]=q.front();
if (son[q.front()][0]) q.push(son[q.front()][0]);
if (son[q.front()][1]) q.push(son[q.front()][1]);
}
}
else if (s[0]=='M'&&s[2]=='K')
pos=in()+1,x=in(),c=in(),
splay(Kth(pos-1),0),
splay(Kth(pos+x),root),
pos=son[root][1],
data[son[pos][0]]=mx[son[pos][0]]=lazy[son[pos][0]]=c,
sum[son[pos][0]]=c*siz[son[pos][0]],
sub[son[pos][0]]=pre[son[pos][0]]=max(0,sum[son[pos][0]]),
maxn[son[pos][0]]=max(sum[son[pos][0]],c),
splay(son[pos][0],0);
else if (s[0]=='R')
pos=in()+1,x=in(),
splay(Kth(pos-1),0),
splay(Kth(pos+x),root),
pos=son[root][1],
rev[son[pos][0]]^=1,
rever(son[pos][0]),
splay(son[pos][0],0);
else if (s[0]=='G')
pos=in()+1,x=in(),
splay(Kth(pos-1),0),
splay(Kth(pos+x),root),
printf("%d\n",sum[son[son[root][1]][0]]);
else
{
splay(Kth(1),0);
splay(Kth(tot),root);
if(maxn[root])printf("%d\n",maxn[root]);
else printf("%d\n",mx[son[son[root][1]][0]]);
}
}
}