zoukankan      html  css  js  c++  java
  • P3369 【模板】普通平衡树 01Trie树

    P3369 【模板】普通平衡树

    题目描述

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

    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 61opt6 )

    输出格式

    对于操作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

    说明/提示

    时空限制:1000ms,128M

    1.n的数据范围: n leq 100000n100000

    2.每个数的数据范围: [-{10}^7, {10}^7][107,107]

    来源:Tyvj1728 原名:普通平衡树

    在此鸣谢

    #include<bits/stdc++.h>
    #define inf 1e7
    using namespace std;
    const int maxn=100005,maxm=maxn*20,N=24;//2^20 
    int ch[maxm][2],v[maxm];
    int cnt=1;
    void Add(int pos,int qx)
    {
        pos+=inf;//防止负数 
        int p=1;//把0号节点空出来 
        for(int i=N;i>=0;i--)
        {
            bool b=(pos>>i)&1;//判断是不是1
            if(!ch[p][b])
                ch[p][b]=++cnt;//动态开点 
            v[p]+=qx;
            p=ch[p][b]; 
        }
        v[p]+=qx;//叶子结点还没有修改 
    }
    int Sum(int pos)
    {
        pos+=inf+1;//+1就是小于等于了 
        int res=0,p=1;
        for(int i=N;i>=0;i--)
        {
            bool b=(pos>>i)&1;
            if(b)// right
                res+=v[ch[p][0]];
            p=ch[p][b];
            if(!p)
                break;
        }
        return res;
    }
    int Get(int rank)
    {
        int p=1,res=0;
        for(int i=N;i>=0;i--)
        {
            if(v[ch[p][0]]>=rank)
                p=ch[p][0];
            else
                rank-=v[ch[p][0]],p=ch[p][1],res|=1<<i;
        }
        return res-inf;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int opt,x;
            scanf("%d%d",&opt,&x);
            if(opt==1)
            {
                Add(x,1);
            }
            if(opt==2)
            {
                Add(x,-1);
            }
            if(opt==3)
            {
                printf("%d
    ",Sum(x-1)+1);
            }
            if(opt==4)
            {
                printf("%d
    ",Get(x));
            }
            if(opt==5)
            {
                int tmp=Sum(x-1)+1;//rank x 
                printf("%d
    ",Get(tmp-1));
            }
            if(opt==6)
            {
                int tmp=Sum(x)+1;//rank x+1
                printf("%d
    ",Get(tmp)); 
            }
        }
        
        
        return 0;
    }

    把数字转化为二进制(当做字符串)存在Trie树上 这类似权值线段树 一个二分的思想

  • 相关阅读:
    sql面试题
    C#基础(1)
    Java中的冒泡排序(减少比较次数)
    Java中面向对象的分拣存储
    Java中分拣存储的demo
    XML序列化
    C#读取csv文件使用字符串拼接成XML
    Java中HashMap(泛型嵌套)的遍历
    Java 中List 集合索引遍历与迭代器遍历
    java 中的try catch在文件相关操作的使用
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/11350309.html
Copyright © 2011-2022 走看看