我尽力了。。。从之前的递归版Splay变成非递归,然后各种删除冗余的操作,除了蛋疼的读入优化基本已经精简到底了,连传参都省了-0- 刚交上去是10956MS,差4MS就是BZOJ倒数第一,改完了是9244MS,快了一秒。。。单点测还是死活过不去,等加上读入优化再说吧
题目大意:维护一个序列,支持六种操作:
1.在某个数后面插入一些数字
2.删除从某个数开始的一些数字
3.把从某个数开始的一些数字都改为某个数值
4.把从某个数开始的一些数字翻转顺序
5.求某个数开始的一些数字的和
6.求出某个数开始的一些数字中的最大子序列之和
首先这个题刚出来的时候Splay还没被发明 正解是块状链表 在这里衷心地感谢Tarjan和他的小伙伴们 顺便问候一下他们的家人 辛苦了
妈蛋挂了两个星期的题终于解决了-、-
一开始写的递归版Splay,每次从爷爷里找孙子,这样就不用存爸爸了,结果无限TLE。。。
然后我就卡关了,再没写过Splay-、- 其实这题不难 时间很好卡
这里给出几个要点和优化方式
1.翻转区间的时候不光要兑换左右儿子,还要交换左右最大连续子序列和 这个坑人不浅啊
2.旋转的时候只需要对旋转后的子节点进行Push_Up操作,当Splay操作退出的时候再对该节点Push_Up即可。
3.这不是LCT,旋转之后要更新根节点!切记!
4.修改标记的初值不能是0 因为会有操作把一段区间改成0 所以初值可以弄成一个数据中绝对不会出现的值 比如生日啥的 当然被撞上了就太倒霉了
5.寻找节点时非递归 不然本地调试第八个点和第十个点会爆栈
6.删除的节点必须free 不然妥妥MLE
总之就这么多 这题不好调 耐心点 链式结构去死吧
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct max_sequence{
int lmax,rmax,allmax,sum;
void un(const max_sequence &x,const max_sequence &y)
{
allmax=max(x.allmax,y.allmax);
allmax=max(allmax,x.rmax+y.lmax);
lmax=max(x.lmax,x.sum+y.lmax);
rmax=max(y.rmax,y.sum+x.rmax);
sum=x.sum+y.sum;
}
void init(int x,int y)
{
if(x>0)
lmax=rmax=allmax=sum=x*y;
else
lmax=rmax=allmax=x,
sum=x*y;
}
};
struct abcd{
abcd *fa;
abcd *ls,*rs;
int size;
int num,maxnum;
max_sequence ms;
int change_mark;
bool revmark;
void Push_Up();
void Push_Down();
abcd(int x);
abcd();
}*null=new abcd,*root=null,*Z,*temp;int Y;
abcd :: abcd()
{
num=maxnum=0xefefefef;
size=0;
fa=ls=rs=this;
ms.init(0xefefefef,0);
}
abcd :: abcd(int x)
{
num=maxnum=x;
size=1;
fa=ls=rs=null;
ms.init(x,1);
change_mark=19980402;
revmark=0;
}
void abcd :: Push_Up()
{
//ls->Push_Down();
//rs->Push_Down();
size=ls->size+rs->size+1;
maxnum=max(max(ls->maxnum,rs->maxnum),num);
ms.init(num,1);
ms.un(ls->ms,ms);
ms.un(ms,rs->ms);
}
void abcd :: Push_Down()
{
if(this==null)
return ;
if(change_mark^19980402)
{
ls->change_mark=rs->change_mark=change_mark;
ls->num=ls->maxnum=change_mark;
rs->num=rs->maxnum=change_mark;
ls->ms.init(change_mark,ls->size);
rs->ms.init(change_mark,rs->size);
change_mark=19980402;
}
if(revmark)
{
ls->revmark^=1;
rs->revmark^=1;
swap(ls->ls,ls->rs);
swap(rs->ls,rs->rs);
swap(ls->ms.lmax,ls->ms.rmax);
swap(rs->ms.lmax,rs->ms.rmax);
revmark=0;
}
}
void Zag(abcd *x)//啦啦啦我是左旋
{
abcd *y=x->fa;
y->Push_Down();
x->Push_Down();
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(root==y)
root=x;
}
void Zig(abcd *x)//啦啦啦我是右旋
{
abcd *y=x->fa;
y->Push_Down();
x->Push_Down();
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(root==y)
root=x;
}
void Splay(abcd *x)
{
while(1)
{
abcd *y=x->fa,*z=y->fa;
if(y==Z)
break;
if(z==Z)
{
if(x==y->ls) Zig(x);
else Zag(x);
break;
}
if(x==y->ls)
{
if(y==z->ls)
Zig(y);
Zig(x);
}
else
{
if(y==z->rs)
Zag(y);
Zag(x);
}
}
x->Push_Up();
}
void Find(abcd *x)
{
while(1)
{
x->Push_Down();
if(Y<=x->ls->size) x=x->ls;
else{
Y-=x->ls->size;
if(Y==1)
break;
Y--;
x=x->rs;
}
}
Splay(x);
}
void Insert(abcd *&x,int y,abcd *from)
{
if(x==null)
{
x=new abcd(y);
x->fa=from;
Z=null;
Splay(x);
return ;
}
x->Push_Down();
Insert(x->rs,y,x);
}
void Free(abcd *x)
{
if(x==null)
return ;
Free(x->ls);
Free(x->rs);
free(x);
}
void INSERT()
{
int i,x,pos,tot;
scanf("%d%d",&pos,&tot);
Y=pos+1,Z=null,Find(root);
Y=pos+2,Z=root,Find(root);
temp=root;root=null;
for(i=1;i<=tot;i++)
scanf("%d",&x),Insert(root,x,null);
temp->rs->ls=root;
root->fa=temp->rs;
root=temp;
root->rs->Push_Up();
root->Push_Up();
}
void DELETE()
{
int pos,tot;
scanf("%d%d",&pos,&tot);
Y=pos,Z=null,Find(root);
Y=pos+tot+1,Z=root,Find(root);
temp=root->rs->ls;
root->rs->ls=null;
root->rs->Push_Up();
root->Push_Up();
Free(temp);
}
void MAKE_SAME()
{
int pos,tot,c;
scanf("%d%d%d",&pos,&tot,&c);
Y=pos,Z=null,Find(root);
Y=pos+tot+1,Z=root,Find(root);
root->rs->ls->change_mark=c;
temp=root->rs->ls;
temp->num=temp->maxnum=c;
temp->ms.init(c,temp->size);
root->rs->Push_Up();
root->Push_Up();
}
void REVERSE()
{
int pos,tot;
scanf("%d%d",&pos,&tot);
Y=pos,Z=null,Find(root);
Y=pos+tot+1,Z=root,Find(root);
temp=root->rs->ls;
temp->revmark^=1;
swap(temp->ls,temp->rs);
swap(temp->ms.lmax,temp->ms.rmax);
}
void GET_SUM()
{
int pos,tot;
scanf("%d%d",&pos,&tot);
Y=pos,Z=null,Find(root);
Y=pos+tot+1,Z=root,Find(root);
printf("%d\n",root->rs->ls->ms.sum);
}
void MAX_SUM()
{
Y=1,Z=null,Find(root);
Y=root->size,Z=root,Find(root);
printf("%d\n",root->rs->ls->ms.allmax);
}
int n,m;
int main()
{
//freopen("sequence.in","r",stdin);
//freopen("sequence.out","w",stdout);
int i,x;
char p[20];
scanf("%d%d",&n,&m);
Insert(root,0,null);
for(i=1;i<=n;i++)
{
scanf("%d",&x);
Insert(root,x,null);
}
Insert(root,0,null);
for(i=1;i<=m;i++)
{
scanf("%s",p);
if(p[2]=='S')INSERT();
else if(p[2]=='L')DELETE();
else if(p[2]=='K')MAKE_SAME();
else if(p[2]=='V')REVERSE();
else if(p[2]=='T')GET_SUM();
else if(p[2]=='X')MAX_SUM();
}
}