luogu2596 [ZJOI2006]书架

treap。树是以“优先级”(优先级越小,在书架上越靠上)形成的,堆是以rand()的权值形成的。还要再维护一个原编号。
置顶/置底:找到那个元素,把它拉出来修改优先级再塞回去。
insert:即一个元素和他“附近”的元素交换位置,把他们两个拉出来,交换优先级再塞回去

#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
int n, m, minn, maxn, a[80005], uu, rot, vv, cnt;
char ss[15];
struct Treap{
	int val[200005], rnd[200005], l[200005], r[200005], siz[200005];
	int bh[200005];
	void upd(int x){
		siz[x] = siz[l[x]] + siz[r[x]] + 1;
	}
	void lRotate(int &k){
		int t=r[k]; r[k] = l[t]; l[t] = k;
		siz[t] = siz[k]; upd(k); k = t;
	}
	void rRotate(int &k){
		int t=l[k]; l[k] = r[t]; r[t] = k;
		siz[t] = siz[k]; upd(k); k = t;
	}
	void insert(int &k, int b){
		if(!k){
			k = ++cnt; val[k] = a[b]; bh[k] = b;
			rnd[k] = rand(); siz[k] = 1;
			return ;
		}
		siz[k]++;
		if(val[k]<a[b]){
			insert(r[k], b);
			if(rnd[r[k]]<rnd[k])	lRotate(k);
		}
		else{
			insert(l[k], b);
			if(rnd[l[k]]<rnd[k])	rRotate(k);
		}
	}
	void shanchu(int &k, int b){
		if(!k)	return ;
		if(val[k]==a[b]){
			if(l[k]*r[k]==0)	k = l[k] + r[k];
			else if(rnd[l[k]]<rnd[r[k]])
				rRotate(k), shanchu(k, b);
			else
				lRotate(k), shanchu(k, b);
		}
		else if(val[k]>a[b])
			siz[k]--, shanchu(l[k], b);
		else
			siz[k]--, shanchu(r[k], b);
	}
	int queryRank(int k, int b){
		if(!k)	return 0;
		if(a[b]<val[k])	return queryRank(l[k], b);
		else if(a[b]>val[k])	return queryRank(r[k], b)+siz[l[k]]+1;
		else	return siz[l[k]]+1;
	}
	int queryNum(int k, int b){
		if(!k)	return 0;
		if(b<=siz[l[k]])	return queryNum(l[k], b);
		else if(b>siz[l[k]]+1)	return queryNum(r[k], b-siz[l[k]]-1);
		else	return bh[k];
	}
}treap;
int main(){
	cin>>n>>m;
	minn = 1; maxn = n;
	for(int i=1; i<=n; i++){
		scanf("%d", &uu);
		a[uu] = i;
		treap.insert(rot, uu);
	}
	while(m--){
		scanf("%s %d", ss, &uu);
		if(ss[0]=='T'){
			treap.shanchu(rot, uu);
			a[uu] = --minn;
			treap.insert(rot, uu);
		}
		if(ss[0]=='B'){
			treap.shanchu(rot, uu);
			a[uu] = ++maxn;
			treap.insert(rot, uu);
		}
		if(ss[0]=='I'){
			scanf("%d", &vv);
			if(vv==0)	continue;
			int t=treap.queryRank(rot, uu);
			int q=treap.queryNum(rot, t+vv);
			treap.shanchu(rot, uu);
			treap.shanchu(rot, q);
			swap(a[uu], a[q]);
			treap.insert(rot, uu);
			treap.insert(rot, q);
		}
		if(ss[0]=='A')
			printf("%d\n", treap.queryRank(rot, uu)-1);
		if(ss[0]=='Q')
			printf("%d\n", treap.queryNum(rot, uu));
	}
	return 0;
}
posted @ 2018-01-30 09:44  poorpool  阅读(141)  评论(0编辑  收藏  举报