• bzoj1861 书架


    题目链接

    思路

    用一个平衡树维护点的编号和权值。这里的权值是自己赋上去的。

    操作1,就把x从平衡树中删掉,然后将其权值变为最小值,重新插入。

    操作2,与操作1类似,只要将其权值变为最大值再重新插入就行了。

    操作3,其实就是将x与他的前驱或者后继交换。也很容易实现。

    操作4,查询排名。

    操作5,查找第k大。

    代码

    /*
    * @Author: wxyww
    * @Date:   2019-05-25 10:50:13
    * @Last Modified time: 2019-05-25 17:21:41
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    #define ls TR[cur].ch[0]
    #define rs TR[cur].ch[1]
    const  int N = 500000 + 100,INF = 1e9 + 10;
    ll read() {
    	ll x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9') {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9') {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    struct node {
    	int ch[2],val,id,key,siz;
    }TR[N];
    int tot;
    int root,dy[N];
    void up(int cur) {
    	TR[cur].siz = TR[ls].siz + TR[rs].siz + 1;
    }
    void rotate(int &cur,int f) {
    	int son = TR[cur].ch[f];
    	TR[cur].ch[f] = TR[son].ch[f ^ 1];
    	TR[son].ch[f ^ 1] = cur;
    	up(cur);
    	cur = son;
    	up(cur);
    }
    void insert(int &cur,int val,int key) {
    	if(!cur) {
    		cur = ++tot;
    		TR[cur].val = val;TR[cur].key = key;
    		TR[cur].id = rand();TR[cur].siz = 1;
    		dy[key] = cur;
    		return;
    	}
    	TR[cur].siz++;
    	int d = val > TR[cur].val;
    	insert(TR[cur].ch[d],val,key);
    	if(TR[TR[cur].ch[d]].id < TR[cur].id) rotate(cur,d);
    }
    void del(int &cur,int val) {
    	if(!cur) return;
    	if(val == TR[cur].val) {
    		if(!ls || !rs) {cur = ls + rs;return;}
    		
    		int d = TR[rs].id < TR[ls].id;rotate(cur,d);
    		del(cur,val);
    	}
    	else TR[cur].siz--,del(TR[cur].ch[val > TR[cur].val],val);
    }
    int Rank(int cur,int val) {
    	if(!cur) return 0;
    	if(val == TR[cur].val) return TR[ls].siz;
    	if(val < TR[cur].val) return Rank(ls,val);
    	else return Rank(rs,val) + TR[ls].siz + 1;
    }
    int kth(int cur,int now) {
    	while(1) {
    		if(TR[ls].siz >= now) cur = ls;
    		else if(TR[ls].siz + 1 == now) return TR[cur].key;
    		else now -= TR[ls].siz + 1,cur = rs;
    	}
    }
    int pred(int cur,int val) {
    	if(!cur) {
    		TR[++tot].val = -INF;
    		return tot;
    	}
    	if(val <= TR[cur].val) return pred(ls,val);
    	int k = pred(rs,val);
    	return TR[k].val > TR[cur].val ? k : cur;
    }
    int nex(int cur,int val) {
    	if(!cur) {
    		TR[++tot].val = INF;
    		return tot;
    	}
    	if(val >= TR[cur].val) return nex(rs,val);
    	int k = nex(ls,val);
    	return TR[k].val < TR[cur].val ? k : cur;
    }
    int LL,RR,a[N];
    char S[10];
    int main() {
    	srand(time(0));
    	int n = read(),m = read();
    	for(int i = 1;i <= n;++i) {
    		int x = read();
    		a[x] = i,insert(root,++RR,x);
    	}
    	while(m--) {
    		scanf("%s",S + 1);
    		if(S[1] == 'T') {
    			int x = read();
    			del(root,a[x]);
    			a[x] = --LL;
    			insert(root,LL,x);
    		}
    		else if(S[1] == 'B') {
    			int x = read();
    			del(root,a[x]);a[x] = ++RR;
    			insert(root,RR,x);
    		}
    		else if(S[1] == 'I') {
    			int x = read(),y = read();
    			if(!y) continue;
    			int tmp;
    			if(y == -1) tmp = pred(root,a[x]);
    			else tmp = nex(root,a[x]);
    			int zz = TR[tmp].key;
    			swap(TR[tmp].key,TR[dy[x]].key);
    			// printf("!!%d %d
    ",x,zz);
    			swap(dy[x],dy[zz]);
    			swap(a[x],a[zz]);
    		}
    		else if(S[1] == 'A') {
    			int x = read();
    			printf("%d
    ",Rank(root,a[x]));
    		}
    		else {
    			int x = read();
    			printf("%d
    ",kth(root,x));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    线程 详解
    登录时,添加图片验证码
    String、StringBuffer、StringBuilder详解
    Random 生成随机数
    down
    九九归一
    小R与手机
    coins
    noip注意事项
    小W计树
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj1861.html
Copyright © 2020-2023  润新知