zoukankan      html  css  js  c++  java
  • 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;
            }
        }
        
    }
    
  • 相关阅读:
    PHP中获取当前页面的完整URL
    phpStydy配置memcache扩展
    mac 安装 php nginx mysql
    mysql分表的3种方法
    Apache虚拟主机配置
    Mysql命令行基本操作
    优化数据库对象
    select,epoll的比较
    lucene合并测试的总结
    验证相关度排序是否受查询的多个关键字在内容中相邻紧密程度有关
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12134772.html
Copyright © 2011-2022 走看看