zoukankan      html  css  js  c++  java
  • BZOJ3224/LOJ104 普通平衡树 treap(树堆)

    您需要写一种数据结构,来维护一些数,其中需要提供以下操作:
    1. 插入x
    2. 删除x(若有多个相同的数,因只删除一个)
    3. 查询x的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)

    1.n的数据范围:$n<=100000$
    2.每个数的数据范围:$[-2e9,2e9]$

    题解:

      二叉搜索树可以完成目标,但是单次操作的时间复杂度可能退化为线性

      因此使用平衡二叉树,$treap$(树堆)

      树堆是各类平衡树中,速度和代码复杂度比较均衡的一个

      速度比splay快且好写,比sbt,替罪羊慢但简单,个人觉得代码比较简单

      BZOJ

      LOJ

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=1e6+10;
    int casn,n,m,k;
    #define nd treap[now]
    #define ndl treap[treap[now].l]
    #define ndr treap[treap[now].r]
    #define ndt treap[tmp]
    struct node {
    	int l,r,val,num,size,rnd;
    }treap[maxn];
    int cnt,root,ans;
    inline void resize(int now){
    	nd.size=ndl.size+ndr.size+nd.num;
    }
    inline void rturn(int &now){
    	int tmp=nd.l;
    	nd.l=ndt.r,ndt.r=now;
    	ndt.size=nd.size;
    	resize(now);
    	now=tmp;
    }
    inline void lturn(int &now){
    	int tmp=nd.r;
    	nd.r=ndt.l,ndt.l=now;
    	ndt.size=nd.size;
    	resize(now);
    	now=tmp;
    }
    void insert(int &now,int val){
    	if(!now) {
    		now=++cnt;
    		nd=(node){0,0,val,1,1,rand()};
    		return ;
    	}
    	nd.size++;
    	if(val==nd.val)nd.num++;
    	else if(val>nd.val){
    		insert(nd.r,val);
    		if(ndr.rnd<nd.rnd) lturn(now);
    	}else{
    		insert(nd.l,val);
    		if(ndl.rnd<nd.rnd) rturn(now);
    	}
    }
    void erase(int &now,int val){
    	if(!now) return ;
    	if(val==nd.val){
    		if(nd.num>1){
    			nd.num--,nd.size--;
    			return ;
    		}
    		if(nd.r*nd.l==0) now=nd.l+nd.r;
    		else {
    			if(ndl.rnd<ndr.rnd) rturn(now);
    			else lturn(now);
    			erase(now,val);
    		}
    	}else {
    		nd.size--;
    		if(val>nd.val) erase(nd.r,val);
    		else erase(nd.l,val);
    	}
    }
    int query_rank(int now,int val){
    	if(!now) return 0;
    	if(val==nd.val)return ndl.size+1;
    	if(val>nd.val) return ndl.size+nd.num+query_rank(nd.r,val);
    	return query_rank(nd.l,val);
    }
    int query_val(int now,int rank){
    	if(!now) return 0;
    	if(rank<=ndl.size) return query_val(nd.l,rank);
    	if(rank-ndl.size<=nd.num) return nd.val;
    	return query_val(nd.r,rank-ndl.size-nd.num);
    }
    int query_pre(int now,int val){
    	if(!now) return ans;
    	if(val<=nd.val) return query_pre(nd.l,val);
    	ans=nd.val;
    	return query_pre(nd.r,val);
    }
    int query_sub(int now,int val){
    	if(!now) return ans;
    	if(val>=nd.val) return query_sub(nd.r,val);
    	ans=nd.val;
    	return query_sub(nd.l,val);
    }
    int main(){
    //#define test
    #ifdef test
      freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    	int root=0;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		int a,b;
    		scanf("%d%d",&a,&b);
    		if(a==1) insert(root,b);
    		if(a==2) erase(root,b);
    		if(a==3) printf("%d
    ",query_rank(root,b));
    		if(a==4) printf("%d
    ",query_val(root,b));
    		if(a==5) printf("%d
    ",query_pre(root,b));
    		if(a==6) printf("%d
    ",query_sub(root,b));
    	}
    #ifdef test
      fclose(stdin);fclose(stdout);system("out.txt");
    #endif
      return 0;
    }
    
  • 相关阅读:
    LINQ N~layer!
    CodeSmith 破解和注册
    鼠标划过链接时弹出窗口
    ajax的loading显示在gridview的位置
    Asp.net与SQL一起打包部署安装
    编译apache报错 No recognized SSL/TLS toolkit detected
    ubuntu12.04 卸载和安装mysql
    Ubuntu12.04 英文环境下使用ibus输入中文并自动启动输入法
    Ubuntu11.10 源码编译安装PHP5.3.8 [转]
    debian 下 编译安装 mysql 二进制文件
  • 原文地址:https://www.cnblogs.com/nervendnig/p/9211681.html
Copyright © 2011-2022 走看看