• 洛谷P2596 [ZJOI2006]书架


    题目

    https://www.luogu.com.cn/problem/P2596

    思路

    这显然是一道数据结构题。

    观察一下要求支持的操作,要是没有top和bottom操作就好了诶,开一个类似map的东西就可以了,然而这两个操作导致了剩余书本的编号和排名的映射关系都发生了变化。

    所以,我们需要一个暴力的数据结构维护书本之间的位置关系,并支持随时插入和删除,那自然就想到splay啦。

    值得注意的是结点i本身就表示编号为i的书,所以并不需要结点权值,建树的时候按照排名顺序依次插入树的末尾即可。

    代码

    #include<cstdlib>
    #include<algorithm>
    #define maxn (int)(8e4+10)
    using namespace std;
    int a[maxn],n,m;
    struct SplayTree{
    	int root,cnt,lc[maxn],rc[maxn],fa[maxn],sz[maxn],rk[maxn];
    	private:
    		void update(int x){
    			if(x) sz[x]=sz[lc[x]]+sz[rc[x]]+1;
    			return;
    		}
    		void zig(int x){
    			int y=fa[x];
    			fa[x]=fa[y];
    			if(fa[y])
    				if(lc[fa[y]]==y) lc[fa[y]]=x;
    				else rc[fa[y]]=x;
    			int z=rc[x];
    			if(z) fa[z]=y;
    			lc[y]=z;
    			fa[y]=x;
    			rc[x]=y;
    			update(y);update(x);
    			return;
    		}
    		void zag(int x){
    			int y=fa[x];
    			fa[x]=fa[y];
    			if(fa[y])
    				if(lc[fa[y]]==y) lc[fa[y]]=x;
    				else rc[fa[y]]=x;
    			int z=lc[x];
    			if(z) fa[z]=y;
    			rc[y]=z;
    			fa[y]=x;
    			lc[x]=y;
    			update(y);update(x);
    			return;
    		}
    		void splay(int x,int r){
    			while(fa[x]!=r){
    				int y=fa[x],z=fa[y];
    				if(z==r){
    					if(lc[y]==x) zig(x);
    					else zag(x);
    				}
    				else{
    					if(lc[y]==x&&lc[z]==y){
    						zig(y);zig(x);
    					}
    					else if(rc[y]==x&&rc[z]==y){
    						zag(y);zag(x);
    					}
    					else if(lc[y]==x&&rc[z]==y){
    						zig(x);zag(x);
    					}
    					else{
    						zag(x);zig(x);
    					}
    				}
    			}
    			if(!r) root=x;
    			return;
    		}
    		int front(int x){
    			while(lc[x]) x=lc[x];
    			return x;
    		}
    		int rear(int x){
    			while(rc[x]) x=rc[x];
    			return x;
    		}
    		void push_front(int now,int x){
    			if(!now){
    				root=x;
    				return;
    			}
    			if(lc[now]) push_front(lc[now],x);
    			else{
    				lc[now]=x;
    				fa[x]=now;
    			}
    			update(now);
    			return;
    		}
    		void push_rear(int now,int x){
    			if(!now){
    				root=x;
    				return;
    			}
    			if(rc[now]) push_rear(rc[now],x);
    			else{
    				rc[now]=x;
    				fa[x]=now;
    			}
    			update(now);
    			return;
    		}
    		void exchange(int x,int y){
    			if(lc[x]==y){
    				rc[y]=rc[x];
    				rc[x]=0;
    				lc[x]=lc[y];
    				lc[y]=x;
    				fa[x]=y;fa[y]=0;
    				if(lc[x]) fa[lc[x]]=x;
    				if(rc[y]) fa[rc[y]]=y;
    			}
    			else{
    				lc[y]=lc[x];
    				lc[x]=0;
    				rc[x]=rc[y];
    				rc[y]=x;
    				fa[x]=y;fa[y]=0;
    				if(rc[x]) fa[rc[x]]=x;
    				if(lc[y]) fa[lc[y]]=y;
    			}
    			update(x);update(y);
    			return;
    		}
    		int get_id(int x,int k){
    			int t=sz[lc[x]];
    			if(t+1==k) return x;
    			if(t+1<k) return get_id(rc[x],k-t-1);
    			else return get_id(lc[x],k);
    		}
    	public:
    		void build(){
    			root=cnt=0;
    			int i;
    			for(i=1;i<=n;i++){
    				lc[i]=rc[i]=fa[i]=0;
    				sz[i]=1;
    			}
    			for(i=1;i<=n;i++){
    				push_rear(root,a[i]);
    				splay(a[i],0);
    			}
    			return;
    		}
    		void top(int x){
    			splay(x,0);
    			if(!lc[x]) return;
    			int y=rear(lc[x]);
    			splay(y,x);
    			rc[y]=rc[x];
    			if(rc[x]) fa[rc[x]]=y;
    			update(y);root=y;fa[y]=0;
    			lc[x]=rc[x]=fa[x]=0;
    			sz[x]=1;
    			push_front(root,x);
    			splay(x,0);
    			return;
    		}
    		void bottom(int x){
    			splay(x,0);
    			if(!rc[x]) return;
    			int y=front(rc[x]);
    			splay(y,x);
    			lc[y]=lc[x];
    			if(lc[x]) fa[lc[x]]=y;
    			update(y);root=y;fa[y]=0;
    			lc[x]=rc[x]=fa[x]=0;
    			sz[x]=1;
    			push_rear(root,x);
    			splay(x,0);
    			return;
    		}
    		void insert(int x,int k){
    			int y;
    			if(!k) return;
    			splay(x,0);
    			if(k==1) y=front(rc[x]);
    			else y=rear(lc[x]);
    			splay(y,x);
    			exchange(x,y);
    			root=y;
    			return;
    		}
    		int ask(int x){
    			splay(x,0);
    			return sz[lc[x]];
    		}
    		int query(int x){
    			return get_id(root,x);
    		}
    } T;
    int main(){
    	int i,s,x;
    	char op[10];
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;++i)
    		scanf("%d",&a[i]);
    	T.build();
    	for(i=1;i<=m;++i){
    		scanf("%s",op);
    		if(op[0]=='T'){
    			scanf("%d",&s);
    			T.top(s);
    		}
    		else if(op[0]=='B'){
    			scanf("%d",&s);
    			T.bottom(s);
    		}
    		else if(op[0]=='I'){
    			scanf("%d%d",&s,&x);
    			T.insert(s,x);
    		}
    		else if(op[0]=='A'){
    			scanf("%d",&s);
    			printf("%d
    ",T.ask(s));
    		}
    		else{
    			scanf("%d",&s);
    			printf("%d
    ",T.query(s));
    		}
    	}
    	// system("pause");
    	return 0;
    }
  • 相关阅读:
    Bash : 冒泡排序
    Azure Load Balancer : 支持 IPv6
    Azure Load Balancer : 简介
    sudo 与输出重定向
    Linux lsof 命令
    Bash : IO 重定向
    LVM : 快照
    2014年全年总结
    使用Kindle4rss推送自己感兴趣的博文
    换SSD硬盘,重装系统,一阵子忙乱
  • 原文地址:https://www.cnblogs.com/landmine-sweeper/p/14717505.html
Copyright © 2020-2023  润新知