您的位置:首页 > 理论基础 > 数据结构算法

BZOJ 1861: [Zjoi2006]Book 书架

2014-03-04 16:03 489 查看
题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1861

题目大意:维护5个操作,具体详见原题(Charlie Pan表示博客写累了~)

算法讨论:

        Splay题。

        Part I 显然Top和Bottom操作是对称的,我们只需将节点旋转到Root后将左右儿子合并即可。

        Part II Insert操作略麻烦……

                我的做法是将左/右子树的最大/小值插入到右/左子树中。

                具体做法还是利用了Splay操作。

                至于其他大神的做法比较神奇,大家可以自行Baidu/Google。

        Part III Ask和Query操作时Splay的基本操作,就不一一赘述了。

Code:

/*
* Problem:1861
* Author:PYC
*/

#include <cstdio>
#include <algorithm>

#define maxn 800000

using namespace std;

char ch;
int n,m,root,a[maxn+1];

struct node{
int l,r,fa,sz;
}tree[maxn+1];

char getopt(){
while (ch!='T' && ch!='B' && ch!='I' && ch!='A' && ch!='Q') ch=getchar();
return ch;
}

int getint(){
while (ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
int x=0;
bool f=0;
if (ch=='-') f=1,ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
if (f) x=-x;
return x;
}

void up(int rt){
tree[rt].sz=tree[tree[rt].l].sz+tree[tree[rt].r].sz+1;
}

void build(int &rt,int l,int r){
int mid=(l+r)/2;
rt=a[mid];
tree[rt].sz=r-l+1;
if (mid-l) build(tree[rt].l,l,mid-1),tree[tree[rt].l].fa=rt;
if (r-mid) build(tree[rt].r,mid+1,r),tree[tree[rt].r].fa=rt;
}

int min_node(int rt){
if (!tree[rt].l) return rt;
return min_node(tree[rt].l);
}

int max_node(int rt){
if (!tree[rt].r) return rt;
return max_node(tree[rt].r);
}

void zig(int rt){
int t=tree[rt].l;
tree[rt].l=tree[t].r;
tree[t].r=rt;
tree[t].fa=tree[rt].fa;
tree[rt].fa=t;
tree[tree[rt].l].fa=rt;
if (rt==tree[tree[t].fa].l) tree[tree[t].fa].l=t;else tree[tree[t].fa].r=t;
up(rt);
up(t);
}

void zag(int rt){
int t=tree[rt].r;
tree[rt].r=tree[t].l;
tree[t].l=rt;
tree[t].fa=tree[rt].fa;
tree[rt].fa=t;
tree[tree[rt].r].fa=rt;
if (rt==tree[tree[t].fa].l) tree[tree[t].fa].l=t;else tree[tree[t].fa].r=t;
up(rt);
up(t);
}

void splay(int x,int &rt){
int fa=tree[rt].fa;
while (tree[x].fa!=fa){
int y=tree[x].fa,z=tree[y].fa;
if (z==fa) if (x==tree[y].l) zig(y);else zag(y);
else if (y==tree[z].l)
if (x==tree[y].l) zig(z),zig(y);else zag(y),zig(z);
else if (x==tree[y].r) zag(z),zag(y);else zig(y),zag(z);
}
rt=x;
}

void top(int x){
splay(x,root);
if (tree[root].r){
splay(min_node(tree[root].r),tree[root].r);
tree[tree[root].r].l=tree[root].l;
tree[tree[root].l].fa=tree[root].r;
tree[root].l=0;
}
else{
tree[root].r=tree[root].l;
tree[root].l=0;
}
up(tree[root].r);
up(root);
}

void bottom(int x){
splay(x,root);
if (tree[root].l){
splay(max_node(tree[root].l),tree[root].l);
tree[tree[root].l].r=tree[root].r;
tree[tree[root].r].fa=tree[root].l;
tree[root].r=0;
}
else{
tree[root].l=tree[root].r;
tree[root].r=0;
}
up(tree[root].l);
up(root);
}

void insert(int x,int mode){
if (!mode) return;
splay(x,root);
if (!tree[root].l && !tree[root].r) return;
if (tree[root].l) splay(max_node(tree[root].l),tree[root].l);
if (tree[root].r) splay(min_node(tree[root].r),tree[root].r);
if (mode==1){
if (tree[root].l){
int rr=tree[tree[root].r].r;
tree[tree[root].r].r=0;
tree[tree[root].r].sz=1;
tree[tree[root].l].r=tree[root].r;
tree[tree[root].r].fa=tree[root].l;
tree[root].r=rr;
tree[tree[root].r].fa=root;
}
else{
int rr=tree[tree[root].r].r;
tree[tree[root].r].r=0;
tree[tree[root].r].sz=1;
tree[root].l=tree[root].r;
tree[root].r=rr;
tree[tree[root].r].fa=root;
}
up(tree[root].l);
up(root);
}
if (mode==-1){
if (tree[root].r){
int ll=tree[tree[root].l].l;
tree[tree[root].l].l=0;
tree[tree[root].l].sz=1;
tree[tree[root].r].l=tree[root].l;
tree[tree[root].l].fa=tree[root].r;
tree[root].l=ll;
tree[tree[root].l].fa=root;
}
else{
int ll=tree[tree[root].l].l;
tree[tree[root].l].l=0;
tree[tree[root].l].sz=1;
tree[root].r=tree[root].l;
tree[root].l=ll;
tree[tree[root].l].fa=root;
}
up(tree[root].r);
up(root);
}
}

int ask(int x){
splay(x,root);
return tree[tree[root].l].sz;
}

int query(int rt,int x){
if (x==tree[tree[rt].l].sz+1) return rt;
if (x<tree[tree[rt].l].sz+1) return query(tree[rt].l,x);
if (x>tree[tree[rt].l].sz+1) return query(tree[rt].r,x-tree[tree[rt].l].sz-1);
}

int main(){
n=getint(),m=getint();
for (int i=1;i<=n;++i) a[i]=getint();
build(root,1,n);
for (int i=1;i<=m;++i){
char opt=getopt();
int x=getint();
if (opt=='T') top(x);
if (opt=='B') bottom(x);
if (opt=='I'){int y=getint();insert(x,y);}
if (opt=='A') printf("%d\n",ask(x));
if (opt=='Q') printf("%d\n",query(root,x));
}
return 0;
}


By Charlie Pan
Mar 4,2014
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息