• luogu P3369 【模板】普通平衡树


    题目描述

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

    插入 (x)
    删除 (x) 数(若有多个相同的数,因只删除一个)
    查询 (x) 数的排名(排名定义为比当前数小的数的个数 (+1) )
    查询排名为 (x) 的数
    (x) 的前驱(前驱定义为小于 (x),且最大的数)
    (x) 的后继(后继定义为大于 (x),且最小的数)

    输入格式

    第一行为 (n),表示操作的个数,下面 (n) 行每行有两个数 ( ext{opt})(x)( ext{opt}) 表示操作的序号( (1 leq ext{opt} leq 6) )

    输出格式

    对于操作 (3,4,5,6) 每行输出一个数,表示对应答案


    Splay

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e6+5,INF=1<<30;
    inline int read(){
    	int x=0,f=1; char c=getchar();
    	while(c<'0'||c>'9'){ if(c=='-')f=-1;  c=getchar(); }
    	while('0'<=c&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar();  }
    	return x*f;	
    }
    int ch[N][2],par[N],val[N],cnt[N],size[N],ncnt,root;
    inline bool chk(int x){ return ch[par[x]][1]==x; }
    inline void pushup(int x){ size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x]; }
    inline void rotate(int x){
    	int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
    	ch[z][chk(y)]=x,par[x]=z;
    	ch[y][k]=w,par[w]=y;
    	ch[x][k^1]=y,par[y]=x;
    	pushup(y),pushup(x);
    }
    inline void splay(int x,int goal=0){
    	while(par[x]!=goal){
    		int y=par[x],z=par[y];
    		if(z!=goal)chk(x)==chk(y)?rotate(y):rotate(x);	
    		rotate(x);
    	}
    	if(!goal)root=x;
    }
    inline void insert(int x){
    	int p=root,cur=0;
    	while(p&&val[p]!=x)cur=p,p=ch[p][x>val[p]];
    	if(p)cnt[p]++;
    	else {
    		p=++ncnt;
    		if(cur)ch[cur][x>val[cur]]=p;
    		ch[p][0]=ch[p][1]=0;
    		par[p]=cur,val[p]=x;
    		cnt[p]=size[p]=1;
    	}
    	splay(p);
    }
    inline void find(int x){
    	int p=root;
    	while(ch[p][x>val[p]]&&x!=val[p])p=ch[p][x>val[p]];
    	splay(p);
    }
    inline int kth(int k){
    	int p=root;
    	while(1){
    		if(ch[p][0]&&k<=size[ch[p][0]])p=ch[p][0];
    		else if(k>size[ch[p][0]]+cnt[p]){
    			k-=size[ch[p][0]]+cnt[p];
    			p=ch[p][1];
    		}else return p;
    	}
    }
    inline int pre(int x){
    	find(x);
    	if(val[root]<x)return root;
    	int p=ch[root][0];
    	while(ch[p][1])p=ch[p][1];
    	return p;	
    }
    inline int succ(int x){
        find(x);
        if(val[root]>x)return root;
        int p=ch[root][1];
        while(ch[p][0])p=ch[p][0];
        return p;
    }
    inline void remove(int x){
    	int last=pre(x),nxt=succ(x);
    	splay(last),splay(nxt,last);
    	int p=ch[nxt][0];
    	if(cnt[p]>1)cnt[p]--,splay(p);
    	else ch[nxt][0]=0;	
    }
    int n,op,x;
    signed main(){
    	n=read();
    	insert(INF);
    	insert(-INF);
    	while(n--){
    		op=read(),x=read();
    		switch (op){
    			case 1: insert(x); break;
    			case 2: remove(x); break;
    			case 3: find(x); printf("%d
    ",size[ch[root][0]]); break;
    			case 4: printf("%d
    ",val[kth(x+1)]); break;
    			case 5: printf("%d
    ",val[pre(x)]); break;
    			case 6: printf("%d
    ",val[succ(x)]); break;
    		}
    	}
    }
    

    Treap

    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define int long long
    const int SIZE=2e5+10;
    struct Treap{
        int l,r;
        int val,dat;
        int cnt,size;
    }a[SIZE];
    int tot,root,n,INF=0x7fffffff;
    inline int New(int val){
        a[++tot].val=val;
        a[tot].dat=rand();
        a[tot].cnt=a[tot].size=1;
        return tot;
    }
    inline void Update(int p){
        a[p].size=a[a[p].l].size+a[a[p].r].size+a[p].cnt;
    }
    inline void Build(){
        New(-INF),New(INF);
        root=1,a[1].r=2;
        Update(root);
    }
    int GetRankByVal(int p,int val){
        if(p==0)return 0;
        if(val==a[p].val)return a[a[p].l].size+1;
        if(val<a[p].val)return GetRankByVal(a[p].l,val);
        return GetRankByVal(a[p].r,val)+a[a[p].l].size+a[p].cnt;
    }
    int GetValByRank(int p,int rank){
        if(p==0)return INF;
        if(a[a[p].l].size>=rank)return GetValByRank(a[p].l,rank);
        if(a[a[p].l].size+a[p].cnt>=rank)return a[p].val;
        return GetValByRank(a[p].r,rank-a[a[p].l].size-a[p].cnt);
    }
    inline void zig(int &p){
        int q=a[p].l;
        a[p].l=a[q].r,a[q].r=p,p=q;
        Update(a[p].r),Update(p);
    }
    inline void zag(int &p){
        int q=a[p].r;
        a[p].r=a[q].l,a[q].l=p,p=q;
        Update(a[p].l),Update(p);
    }
    inline void Insert(int &p,int val){
        if(p==0){
            p=New(val);
            return;
        }
        if(val==a[p].val){
            a[p].cnt++,Update(p);
            return;
        }
        if(val<a[p].val){
            Insert(a[p].l,val);
            if(a[p].dat<a[a[p].l].dat)zig(p);
        }else{
            Insert(a[p].r,val);
            if(a[p].dat<a[a[p].r].dat)zag(p);
        }
        Update(p);
    }
    inline int GetPre(int val){
        int ans=1,p=root;
        while(p){
            if(val==a[p].val){
                if(a[p].l){
                    p=a[p].l;
                    while(a[p].r)p=a[p].r;
                    ans=p;
                }
                break;
            }
            if(a[p].val<val&&a[p].val>a[ans].val)ans=p;
            p=val<a[p].val?a[p].l:a[p].r;
        }
        return a[ans].val;
    }
    inline int GetNext(int val){
        int ans=2,p=root;
        while(p){
            if(val==a[p].val){
                if(a[p].r){
                    p=a[p].r;
                    while(a[p].l)p=a[p].l;
                    ans=p;
                }
                break;
            }
            if(a[p].val>val&&a[p].val<a[ans].val)ans=p;
            p=val<a[p].val?a[p].l:a[p].r;
        }
        return a[ans].val;
    }
    void Remove(int &p,int val){
        if(p==0)return;
        if(val==a[p].val){
            if(a[p].cnt>1){
                a[p].cnt--,Update(p);
                return;
            }
            if(a[p].l||a[p].r){
                if(a[p].r==0||a[a[p].l].dat>a[a[p].r].dat)zig(p),Remove(a[p].r,val);
                else zag(p),Remove(a[p].l,val);
                Update(p);
            }
            else p=0;
            return;
        }
        val<a[p].val?Remove(a[p].l,val):Remove(a[p].r,val);
        Update(p);
    }
    signed main(){
        srand(time(0));
        Build();
        cin>>n;
        while(n--){
            int opt,x;
            scanf("%lld%lld",&opt,&x);
            switch(opt){
                case 1:
                    Insert(root,x);
                    break;
                case 2:
                    Remove(root,x);
                    break;
                case 3:
                    printf("%lld
    ",GetRankByVal(root,x)-1);
                    break;
                case 4:
                    printf("%lld
    ",GetValByRank(root,x+1));
                    break;
                case 5:
                    printf("%lld
    ",GetPre(x));
                    break;
                case 6:
                    printf("%lld
    ",GetNext(x));
                    break;
            }
        }
        
    }
    
  • 相关阅读:
    react Native 运行报错之一 gradle-2.14.1-all解压失败的问题
    react native windows create bundle folder
    gulp+browserSync+nodemon 实现express 全端自动刷新的实践
    nodejs框架express4.x 学习--安装篇
    转: angularjs 指令中动态编译的方法(适用于有异步请求的情况) 内嵌指令无效
    angular 基础练习
    自己写的数组排重+排序
    前端开发bower包管理器
    定位网站性能的一些经验
    记一次大规模数据迁移和加密
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12134772.html
Copyright © 2020-2023  润新知