您的位置:首页 > 大数据 > 人工智能

hdu3487 Play with Chain 伸展树splay

2013-10-08 19:24 465 查看
       一个长度为n的数列,初始状态为1,2...n。现有两种操作,CUT a,b,c 将从a开始到b结束这段数取出,并把这段插入到取出之后这个数列的第c个数后面;FLIP a,b 将从a开始到c结束的这段数颠倒顺序。 还是基本的splay操作,为了操作方便,先添加虚拟的头结点和尾节点,再把这串数插入到头尾之间。CUT操作就把a伸展到根,把b+2伸展到根的下面,这样b+2的左孩子就是目标段a+1,b+1了(因为有个虚拟节点所以a+1,b+1对应的就是原先的a,b),然后删掉b+2的左子树,再把c伸展到根,c+1伸展到根的下面,把刚刚删除的子树插入到根的右孩子的左孩子就ok了。FLIP还是把a伸展到根,b+2伸展到根的下面,给目标段上标记就可以了。最后中序遍历的时候不要忘了下传下标..

       

       一个长度为n的数列,初始状态为1,2...n。现有两种操作,CUT a,b,c 将从a开始到b结束这段数取出,并把这段插入到取出之后这个数列的第c个数后面;FLIP a,b 将从a开始到c结束的这段数颠倒顺序。 还是基本的splay操作,为了操作方便,先添加虚拟的头结点和尾节点,再把这串数插入到头尾之间。CUT操作就把a伸展到根,把b+2伸展到根的下面,这样b+2的左孩子就是目标段a+1,b+1了(因为有个虚拟节点所以a+1,b+1对应的就是原先的a,b),然后删掉b+2的左子树,再把c伸展到根,c+1伸展到根的下面,把刚刚删除的子树插入到根的右孩子的左孩子就ok了。FLIP还是把a伸展到根,b+2伸展到根的下面,给目标段上标记就可以了。最后中序遍历的时候记得下传下标...

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=300000+300;
int pre[maxn],ch[maxn][2];
int size[maxn],key[maxn];
int flip[maxn];
int root,n;
int tot;
int m,p,q,r,t,tt;
int k1,k2;
int a[maxn];
int b[maxn];
int num;
struct splaytree
{
void pushup(int r)
{
size[r]=1+size[ch[r][0]]+size[ch[r][1]];
}
void go_f(int r)
{
flip[r]^=1;
swap(ch[r][0],ch[r][1]);
}
void pushdown(int r)
{
if (flip[r])
{
go_f(ch[r][0]);
go_f(ch[r][1]);
flip[r]=0;
}
}
void rotate(int x,int kind)
{
int y=pre[x];
pushdown(y);
pushdown(x);
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if (pre[y])
{
ch[pre[y]][ch[pre[y]][1]==y]=x;
}
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
pushup(y);
pushup(x);
}
void splay(int x,int tgt)
{
pushdown(x);
while(pre[x]!=tgt)
{
int y=pre[x];
pushdown(pre[y]);
pushdown(y);
pushdown(x);
if (pre[pre[x]]==tgt)
{
rotate(x,ch[pre[x]][0]==x);
}
else
{
int kind=ch[pre[y]][0]==y;
if (ch[y][kind]==x)
{
rotate(x,kind^1);
rotate(x,kind);
}
else
{
rotate(y,kind);
rotate(x,kind);
}
}
}
pushup(x);
if (tgt==0) root=x;
}
void select(int k,int tgt)
{
int rt=root;
pushdown(rt);
while(true)
{
if (k<=size[ch[rt][0]]) rt=ch[rt][0];
else if (k==size[ch[rt][0]]+1) break;
else k-=(size[ch[rt][0]]+1),rt=ch[rt][1];
pushdown(rt);
}
splay(rt,tgt);
}
void newnode(int &r,int father,int k)
{
r=++tot;
pre[r]=father;
size[r]=1;
flip[r]=0;
key[r]=k;
ch[r][0]=ch[r][1]=0;
}
void build(int l,int r,int &x,int rt)
{
if (l>r) return;
int m=(l+r)>>1;
newnode(x,rt,m);
build(l,m-1,ch[x][0],x);
build(m+1,r,ch[x][1],x);
pushup(x);
}
void init()
{
tot=root=0;
newnode(root,0,0);
newnode(ch[root][1],root,0);
build(1,n,ch[ch[root][1]][0],ch[root][1]);
pushup(ch[root][1]);
pushup(root);
}
void Flip(int p1,int p2)
{
select(p1,0);
select(p2+2,root);
go_f(ch[ch[root][1]][0]);
}
void cut(int l1,int l2,int l3)
{
int t;
select(l1,0);
select(l2+2,root);
t=ch[ch[root][1]][0];
pre[t]=0;
ch[ch[root][1]][0]=0;
pushup(ch[root][1]);
select(l3+1,0);
select(l3+2,root);
ch[ch[root][1]][0]=t;
pre[t]=ch[root][1];
}
void print(int rt)
{
if (rt==0) return;
pushdown(rt);
print(ch[rt][0]);
if (key[rt])
{
num++;
b[num]=key[rt];
}
print(ch[rt][1]);
}
void out()
{
num=0;
print(root);
for (int i=1; i<num; i++)
printf("%d ",b[i]);
printf("%d\n",b[num]);
}
}spt;
char cmd[20];
int x,y,z;
int main()
{
//    freopen("in.txt","r",stdin);
while(~scanf("%d%d\n",&n,&m) && (n!=-1 || m!=-1))
{
spt.init();
for (int i=1; i<=m; i++)
{
scanf("%s ",cmd);
if (cmd[0]=='C')
{
scanf("%d%d%d",&x,&y,&z);
spt.cut(x,y,z);
}
else
{
scanf("%d%d",&x,&y);
spt.Flip(x,y);
}
}
spt.out();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: