zoukankan      html  css  js  c++  java
  • [luogu3369] 普通平衡树(splay模板)

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1.插入 xx 数
    2.删除 xx 数(若有多个相同的数,因只删除一个)
    3.查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
    4.查询排名为 xx 的数
    5.求 xx 的前驱(前驱定义为小于 xx ,且最大的数)
    6.求 xx 的后继(后继定义为大于 xx ,且最小的数)

    输入输出格式

    输入格式:
    第一行为 nn ,表示操作的个数,下面 nn 行每行有两个数 optopt 和 xx , optopt 表示操作的序号( 1 leq opt leq 6 1≤opt≤6 )

    输出格式:
    对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案

    输入输出样例

    输入样例#1:
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    输出样例#1:
    106465
    84185
    492737

    说明

    code:

    //By Menteur_Hxy
    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long
    #define M(a,b) memset(a,(b),sizeof(a))
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define C(i,a,b) for(register int i=(b);i>=(a);i--)
    #define E(i,u) for(register int i=head[u];i;i=nex[i])
    using namespace std;
    
    inline LL rd() {
    	LL x=0,fla=1; char c=' ';
    	while(c>'9'|| c<'0') {if(c=='-') fla=-fla; c=getchar();}
    	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
    	return x*fla;
    }
    
    inline void out(LL x){
        int a[25],wei=0;
        if(x<0) putchar('-'),x=-x;
        for(;x;x/=10) a[++wei]=x%10;
        if(wei==0){ puts("0"); return;}
        for(int j=wei;j>=1;--j) putchar('0'+a[j]);
        putchar('
    ');
    }
    /*--splay_begin--*/ 
    #define check(x) (x==nd[fa[x]][1])
    #define clear(x) key[x]=cnt[x]=siz[x]=fa[x]=nd[x][1]=nd[x][0]=0
    #define update(x) siz[x]=siz[nd[x][1]]+siz[nd[x][0]]+cnt[x]
    const int N=100005;
    int key[N],cnt[N],siz[N],fa[N],nd[N][2];
    int size,root;
    
    inline int newnode(int x) {key[++size]=x,cnt[size]=siz[size]=1;return size;}
    inline void rotate(int x) { int old=fa[x],oldf=fa[old];
    	bool wh=check(x);
    	fa[nd[x][wh^1]]=old; nd[old][wh]=nd[x][wh^1];
    	nd[x][wh^1]=old; fa[old]=x; fa[x]=oldf;
    	if(oldf) nd[oldf][nd[oldf][1]==old]=x;
    	update(old);update(x);
    }
    inline void splay(int x) {
    	for(int f=fa[x];f;rotate(x),f=fa[x])
    		if(fa[f]) rotate(check(f)==check(x)?f:x);
    	root=x;
    }
    inline void insert(int x) {
    	if(!root) {root=newnode(x);return ;}
    	int now=root,f=0;
    	while(1) {
    		if(key[now]==x) {cnt[now]++;update(now);update(f);splay(now);return ;}
    		f=now,now=nd[now][x>key[now]];
    		if(!now) {now=newnode(x);fa[now]=f;nd[f][x>key[f]]=now;update(f);splay(now);return ;}
    	}
    }
    inline int rk(int x) { int now=root,ans=0;
    	while(1) {
    		if(x<key[now]) now=nd[now][0];
    		else {
    			ans+=siz[nd[now][0]];
    			if(key[now]==x) return splay(now),ans+1;
    			ans+=cnt[now]; now=nd[now][1];
    		}
    	}
    }
    inline int kth(int x) { int now=root;
    	while(1) {
    		if(nd[now][0]&&x<=siz[nd[now][0]]) now=nd[now][0];
    		else {
    			x-=siz[nd[now][0]]+cnt[now];
    			if(x<=0) return now;
    			now=nd[now][1];
    		}
    	}
    }
    inline int prenxt(int now) { int wh=check(now);
    	while(nd[now][wh^1]) now=nd[now][wh^1];
    	return now;
    }
    inline void del(int x) {
    	rk(x);
    	if(cnt[root]>1) {cnt[root]--;update(root);return ;}
    	if(!nd[root][0]&&!nd[root][1]) {clear(root);root=0;return ;}
    	if(!nd[root][0]) {int old=root;root=nd[root][1];fa[root]=0;clear(old);return ;}
    	if(!nd[root][1]) {int old=root;root=nd[root][0];fa[root]=0;clear(old);return ;}
    	int old=root;
    	splay(prenxt(nd[root][0]));
    	nd[root][1]=nd[old][1];
    	fa[nd[old][1]]=root;
    	clear(old);
    	update(root);
    	return ; 
    }
    /*--splay_end--*/
    int main() {
        int n=rd();
        for(int i=1;i<=n;i++) { int opt=rd(),x=rd();
            switch(opt) { 
                case 1:insert(x);break;
                case 2:del(x);break;
                case 3:out(rk(x));break;
                case 4:out(key[kth(x)]);break;
                case 5:insert(x);out(key[prenxt(nd[root][0])]);del(x);break;
                case 6:insert(x);out(key[prenxt(nd[root][1])]);del(x);break;   
            }
        }
        return 0;
    }
    
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    A CIRCULAR PROGRESSBAR STYLE USING AN ATTACHED VIEWMODEL
    First MarkDown Blog
    Folder Recursion with C#
    39. Volume Rendering Techniques
    Service Station
    WPF Wonders: Transformations (and Robots!)
    Flipping elements with WPF
    FoLlow 的技术博客
    利用索引降低并发事务引起的锁【转】
    企业级应用架构模型-并发,事务,锁
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9184061.html
Copyright © 2011-2022 走看看