zoukankan      html  css  js  c++  java
  • 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
    ", treap.queryRank(rot, uu)-1);
    		if(ss[0]=='Q')
    			printf("%d
    ", treap.queryNum(rot, uu));
    	}
    	return 0;
    }
    
  • 相关阅读:
    数据机构与算法学习(四)- 链表
    DFS深度优先
    LeetCode.98验证二叉树
    输入一个有符号整数,输出该整数的反转值。
    如何交换两个对象
    泛型简介,泛型类及使用
    一个普通的逻辑问题
    for循环
    第一次比赛唯一ACCEPT的题目笑哭
    输入100以内具有10个以上因子的整数 并输出它的因子
  • 原文地址:https://www.cnblogs.com/poorpool/p/8383628.html
Copyright © 2011-2022 走看看