BZOJ跪了我找了好多OJ才又找到维护数列这个题~话说SPOJ好像比较慢的样子~我找别人以前在BZOJ上AC的程序在SPOJ上竟然TLE了~加了读入优化还是TLE~囧~这算个什么事~今天把splay的数组实现改成了指针实现以后终于AC掉了~完全不知道我的splay哪里写慢了QAQ
splay总体来说就是转来转去转来转去【转晕了诶】各种操作都是在旋转的基础上完成的。splay因为不需要维护树的严格平衡,可以实现很多其它平衡树不能完成的操作。总体来说splay的功能有如下一些:
单点插入、查询、删除(所有平衡树都可以)
单点、成段更新(其它平衡树不能、线段树和splay可以)(呃~好像其它平衡树可以单点更新的样子呢喵)
成段插入、删除、区间翻转(其它平衡树和线段树都不能,只有splay可以)
也就是说,splay可以代替线段树,但是和线段树比起来代码量过大了QAQ
对区间的操作方式是:把区间左端点的左边一位转到根,右端点的右边一位转到根的右子树,这样根的右子树的左子树就是要操作的区间。开始建树时要在树上建两-INF的结点保证区间的两个端点一定存在。
【
2012-12-26
关于splay的双旋转,要这样旋转的原因是为了维护splay的相对平衡,如果总是转x结点一直转到根那么一条链转完以后还是一条链,而使用双旋转则可以使旋转后的splay变得相对平衡。这一部分在杨思雨的论文里有详细的图解。
】
更具体一些的可以围观Crash神的论文
囧~话说平衡树我是先学的SBT,没学splay是因为我当时不会线段树,本来是要交给蛋蛋去学的~然后我之所以不会线段树是因为觉得他俩都会了我就不学了QAQ然后~我还是学了~学完以后发现这玩意好简单……然后开始折腾splay【是这货折腾我】……理论到是不难~写起来还真是各种纠结~围观了Crash神的论文和各位神的代码终于搞明白了OTL
下面送上我的splay模板~个人觉得写得还是很清晰的~
/*
插入:INSERT pos n c1...cn (pos后面插入n个数字)
删除:DELETE pos n (删除pos开始的n个数字)
修改:MAKE-SAME pos n c (pos开始的n个数字修改为c)
翻转:REVERSE pos n (pos开始的n个数字翻转)
求和:GET-SUM pos n (pos开始的n个数字求和)
求和最大的子序列:MAX-SUM (整个区间的和最大的子序列)
*/
#include <cstdio>
#include <iostream>
using namespace std;
#define INF 1<<30
#define N 500010
int n,m;
int num[N];
struct node
{
node *ch[2],*pre;
int sz,val,sum,ls,rs,ss;
bool lzy1;
int lzy2;
};
struct SplayTree
{
node *root,*null,*pool[N],data[N];
int n,cnt,top;
void rotate(node *x,int f)//旋转
{
node *y=x->pre,*z=y->pre;
push_down(y);
push_down(x);
y->ch[!f]=x->ch[f];
x->ch[f]->pre=y;
x->ch[f]=y;
y->pre=x;
x->pre=z;
if(x->pre!=null) z->ch[z->ch[1]==y]=x;
push_up(y);
}
void splay(node *x,node *goal)//把x节点转到goal下面,goal为0表示转到根
{
push_down(x);
while (x->pre!=goal)
{
if(x->pre->pre==goal) rotate(x,x->pre->ch[0]==x);
else
{
node *y=x->pre,*z=y->pre;
int f=(z->ch[0]==y);
if(y->ch[f]==x) rotate(x,!f);
else rotate(y,f);
rotate(x,f);
}
}
push_up(x);
if(goal==null) root=x;
}
void rotateto(int k,node *goal)//把第k位转到goal下面
{
node *x=root;
push_down(x);
while (x->ch[0]->sz!=k)
{
if(k<x->ch[0]->sz) x=x->ch[0];
else{
k-=x->ch[0]->sz+1;
x=x->ch[1];
}
push_down(x);
}
splay(x,goal);
}
//以上函数基本不用变
void clear()
{
n=top=0;
null=newnode(-INF);
null->sz=null->sum=0;
null->val=null->ls=null->rs=null->ss=-INF;
null->lzy1=0;
null->lzy2=-INF;
root=newnode(-INF);
root->ch[1]=newnode(-INF);
root->ch[1]->pre=root;
root->sz=2;
}
node *newnode(int c)
{
node *x;
if (top) x=pool[top--];
else x=&data[n++];
x->ch[0]=x->ch[1]=x->pre=null;
x->sz=1;
x->val=x->ls=x->rs=x->ss=x->sum=c;
x->lzy1=0;
x->lzy2=-INF;
return x;
}
void push_up(node *x)
{
node *lx=x->ch[0],*rx=x->ch[1];
x->sz=1+lx->sz+rx->sz;
x->sum=x->val+lx->sum+rx->sum;
x->ls=max(lx->ls,lx->sum+x->val+max(0,rx->ls));
x->rs=max(rx->rs,rx->sum+x->val+max(0,lx->rs));
x->ss=max(0,lx->rs)+x->val+max(0,rx->ls);
x->ss=max(x->ss,max(lx->ss,rx->ss));
}
void update_rev(node *x)
{
if(x==null) return;
swap(x->ch[0],x->ch[1]);
swap(x->ls,x->rs);
x->lzy1^=1;
}
void update_same(node *x,int v)
{
if(x==null) return;
x->val=v;
x->sum=v*x->sz;
x->ss=x->ls=x->rs=max(v,v*x->sz);
x->lzy2=v;
}
void push_down(node *x)
{
if(x->lzy1)
{
update_rev(x->ch[0]);
update_rev(x->ch[1]);
x->lzy1=0;
}
if(x->lzy2!=-INF)
{
update_same(x->ch[0],x->lzy2);
update_same(x->ch[1],x->lzy2);
x->lzy2=-INF;
}
}
void init(int pos,int tot)
{
clear();
cnt=tot;
rotateto(pos,null);
rotateto(pos+1,root);
root->ch[1]->ch[0]=build(1,tot,root->ch[1]);
push_up(root->ch[1]);
push_up(root);
}
node *build(int l,int r,node *f)
{
if(l>r) return null;
push_down(f);
int mid=(l+r)>>1;
node *x=newnode(num[mid]);
x->ch[0]=build(l,mid-1,x);
x->ch[1]=build(mid+1,r,x);
x->pre=f;
push_up(x);
return x;
}
void ins(int pos,int len)
{
cnt+=len;
rotateto(pos,null);
rotateto(pos+1,root);
root->ch[1]->ch[0]=build(1,len,root->ch[1]);
push_up(root->ch[1]);
push_up(root);
}
void erase(node *x)
{
if(x==null) return;
pool[++top]=x;
erase(x->ch[0]);
erase(x->ch[1]);
}
void del(int l,int r)
{
rotateto(l-1,null);
rotateto(r+1,root);
node *key=root->ch[1]->ch[0];
root->ch[1]->ch[0]=null;
cnt-=key->sz;
erase(key);
push_up(root->ch[1]);
push_up(root);
}
void change(int l,int r,int c)
{
rotateto(l-1,null);
rotateto(r+1,root);
node *key=root->ch[1]->ch[0];
update_same(key,c);
push_up(root->ch[1]);
push_up(root);
}
void flip(int l,int r)
{
rotateto(l-1,null);
rotateto(r+1,root);
node *key=root->ch[1]->ch[0];
update_rev(key);
}
int get_sum(int l,int r)
{
rotateto(l-1,null);
rotateto(r+1,root);
node *key=root->ch[1]->ch[0];
return key->sum;
}
int max_sum()
{
rotateto(0,null);
rotateto(cnt+1,root);
node *key=root->ch[1]->ch[0];
return key->ss;
}
void print(node *x)
{
if(x->ch[0]!=null) print(x->ch[0]);
printf("%d ",x->val);
if(x->ch[1]!=null) print(x->ch[1]);
}
}spl;
int main ()
{
int tt;
int i,j,t;
int a,b,c;
char op[30];
scanf("%d",&tt);
while (tt--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) scanf("%d",&num[i]);
spl.init(0,n);
/*spl.print(spl.root);
printf("\n");
return 0;*/
while (m--)
{
scanf("%s",op);
if(op[0]=='I')
{
scanf("%d%d",&a,&n);
for(i=1;i<=n;i++) scanf("%d",&num[i]);
spl.ins(a,n);
}else
if(op[0]=='D')
{
scanf("%d%d",&a,&b);
spl.del(a,a+b-1);
}else
if(op[0]=='M' && op[2]=='K')
{
scanf("%d%d%d",&a,&b,&c);
spl.change(a,a+b-1,c);
}else
if(op[0]=='R')
{
scanf("%d%d",&a,&b);
spl.flip(a,a+b-1);
}else
if(op[0]=='G')
{
scanf("%d%d",&a,&b);
printf("%d\n",spl.get_sum(a,a+b-1));
}
else if(op[0]=='M') printf("%d\n",spl.max_sum());
}
}
return 0;
}