• Tyvj 1728 普通平衡树



    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)
    Input
    第一行为n,表示操作的个数
    下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
    1.n的数据范围:n<=100000
    2.每个数的数据范围:[-2e9,2e9]
    Output
    对于操作3,4,5,6每行输出一个数,表示对应答案

    Sample Input
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    Sample Output
    106465
    84185
    492737

    Sol:相当于建立一个权值线段树

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define setIO(s) freopen(s".in","r",stdin)
    #define maxn 100010 * 33 
    using namespace std;
    int root=1,tot=1,sumv[maxn],n,opt,x,ch[maxn][2]; 
    void ins(int val,int c)
    {
        val += (int)1e7;
        for(int i=31,p=root,t;i>=0;--i)
    	{
            t=(val>>i)&1;
            if(!ch[p][t]) 
    ch[p][t]=++tot;
            p=ch[p][t]; 
    		sumv[p]+=c; 
        }
    }
    int rankk(int val)
    //查询x数的排名 
    {
        val += (int)1e7; //统一加上一个正数,避免负数的出现 
        int res=0,p=root; 
        for(int i=31;i>=0;--i)
    	{
            int t=(val>>i)&1;
            if(t) //如果T为1,则大于所有P结点的0那个子结点的所有数字 
    res += sumv[ch[p][0]];
            p=ch[p][t]; 
        }
        return res; 
        //对于val来说有res个数字比它小,所以它排名第res+1 
    }
    int kth(int val) //查询排名为x的数 
    {
        int k=root,res=0;
        for(int i=31;i>=0;--i)
    	{
            if(val>sumv[ch[k][0]]) 
               res|=(1<<i),val-=sumv[ch[k][0]],k=ch[k][1];
            else 
               k=ch[k][0]; 
        } 
        res-=(1e7); 
    	return res; 
    }
    int main(){
        //setIO("input");
        scanf("%d",&n);
        while(n--){
            scanf("%d%d",&opt,&x);
            if(opt==1) 
               ins(x,1);
            else 
    			if(opt==2) 
    				ins(x,-1);
    			else 
    			if(opt==3) 
    				//查询x数的排名     
    				printf("%d
    ",rankk(x)+1);
    			else 
    				if(opt==4) 
    		               //查询排名为x的数
    					printf("%d
    ",kth(x));
    				else 
    					if(opt==5) 
    		                //求x的前驱(前驱定义为小于x,且最大的数)
    						printf("%d
    ",kth(rankk(x)));
    					else 
    					if(opt==6) 
    		               //求x的后继(后继定义为大于x,且最小的数
    						printf("%d
    ",kth(rankk(x+1)+1)); 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    7,MongoDB 之 Limit 选取 Skip 跳过 Sort 排序
    Python的while else
    linux route
    NCO
    rand和randn
    vi常用操作
    Linux常用命令
    Jmeter的NON-GUI模式
    Linux下安装jdk&Jmeter
    MySql安装完成后,Navicat连接不上的问题
  • 原文地址:https://www.cnblogs.com/cutemush/p/12642903.html
Copyright © 2020-2023  润新知