zoukankan      html  css  js  c++  java
  • BZOJ 3224 Tyvj 1728 普通平衡树模板

    题目链接:

    https://www.lydsy.com/JudgeOnline/problem.php?id=3224

    题目大意:

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

    思路:

    splay:http://www.cnblogs.com/BCOI/p/9010229.html

    treap:https://www.cnblogs.com/BCOI/p/9072444.html

      1 #include<bits/stdc++.h>
      2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
      3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
      4 #define Min(a, b) ((a) < (b) ? (a) : (b))
      5 #define Mem(a) memset(a, 0, sizeof(a))
      6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
      7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
      8 #define lson ((o)<<1)
      9 #define rson ((o)<<1|1)
     10 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
     11 using namespace std;
     12 inline int read()
     13 {
     14     int x=0,f=1;char ch=getchar();
     15     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     16     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 
     20 typedef long long ll;
     21 const int maxn = 1000000 + 10;
     22 const int MOD = 1000000007;//const引用更快,宏定义也更快
     23 const int INF = 1e9 + 7;
     24 const double eps = 1e-6;
     25 
     26 struct node
     27 {
     28     int fa;//记录父节点
     29     int ch[2];//ch[0]表示左儿子 ch[1]表示右儿子
     30     int val;//节点权值
     31     int Size;//记录节点子树大小(包括该节点)
     32     int cnt;//记录同样权值的元素个数
     33     int mark;//记录反转区间标记(普通平衡树不用)
     34 }t[maxn];
     35 int root = 0;//根节点
     36 int cnt = 0;//当前节点数目
     37 bool get(int x)//判断一个节点是左节点还是右节点
     38 {
     39     return t[t[x].fa].ch[1] == x;//右节点返回1 左节点返回0
     40 }
     41 void up(int x)//重新统计节点x的size
     42 {
     43     t[x].Size = t[t[x].ch[0]].Size + t[t[x].ch[1]].Size + t[x].cnt;
     44 }
     45 void Rotate(int x)//节点x与父节点旋转
     46 {
     47     int fa = t[x].fa, gfa = t[fa].fa;
     48     int d1 = get(x), d2 = get(fa);//加上d1 d2均表示左儿子
     49     t[fa].ch[d1] = t[x].ch[d1 ^ 1]; t[t[x].ch[d1 ^ 1]].fa = fa;//父节点的左儿子设置成左儿子的右儿子(双向设置)
     50     t[gfa].ch[d2] = x; t[x].fa = gfa;//祖父节点的左儿子设置成父节点的左儿子(双向)
     51     t[fa].fa = x; t[x].ch[d1^1] = fa;//左儿子的右儿子设置成父节点(双向)
     52     up(fa); up(x);
     53 }
     54 void splay(int x, int goal)//x旋转到goal下面
     55 {
     56     while(t[x].fa != goal)
     57     {
     58         int fa = t[x].fa, gfa = t[fa].fa;
     59         int d1 = get(x), d2 = get(fa);
     60         if(gfa != goal)
     61         {
     62             if(d1 == d2)Rotate(fa);//同侧,先旋父节点(双旋)
     63             else Rotate(x);//异侧 直接选
     64         }
     65         Rotate(x);//再向上旋一次
     66     }
     67     if(goal == 0)root = x;
     68 }
     69 void Insert(int val)
     70 {
     71     int node = root, fa = 0;
     72     while(node && t[node].val != val)
     73         fa = node, node = t[node].ch[t[node].val < val];
     74     if(node)t[node].cnt++;//节点存在
     75     else
     76     {
     77         node = ++cnt;
     78         if(fa)t[fa].ch[t[fa].val < val] = node;
     79         t[node].fa = fa;
     80         t[node].Size = t[node].cnt = 1;
     81         t[node].val = val;
     82     }
     83     splay(node, 0);//将新节点旋到根来维护splay的子树
     84 }
     85 int kth(int k)//查询第k大的数
     86 {
     87     int node = root;
     88     while(1)
     89     {
     90         int son = t[node].ch[0];
     91         if(k <= t[son].Size)node = son;
     92         else if(k > t[son].Size + t[node].cnt)
     93         {
     94             k -= t[son].Size + t[node].cnt;
     95             node = t[node].ch[1];
     96         }
     97         else return t[node].val;
     98     }
     99 }
    100 int Find(int val)//直接调用Find(INF)或者调用Find(-INF)可以得到最大值和最小值编号
    101 {
    102     int node = root;
    103     while(t[node].val != val && t[node].ch[t[node].val < val])
    104         node = t[node].ch[t[node].val < val];
    105     return node;
    106 }
    107 int get_rank(int val)//查询一个数的排名
    108 {
    109     splay(Find(val), 0);
    110     return t[t[root].ch[0]].Size + 1;
    111 }
    112 int get_pre(int val, int kind)//kind = 0 查询前驱 kind = 1查询后继
    113 {
    114     splay(Find(val), 0);
    115     int node = root;
    116     if(t[node].val < val && kind == 0)return node;
    117     if(t[node].val > val && kind == 1)return node;//根节点就是前驱/后继的情况
    118     node = t[node].ch[kind];
    119     while(t[node].ch[kind ^ 1])node = t[node].ch[kind ^ 1];//否则在子树中寻找最值
    120     return node;//返回的是编号 具体的值调用需要用t[node].val
    121 }
    122 void delet(int val)
    123 {
    124     int last = get_pre(val, 0);//由于此处查询了前驱和后缀 可能会查询到最小值的前驱或者最大值的后缀
    125     int next = get_pre(val, 1);//必须事先加入INF 和-INF 不然会出错
    126     splay(last, 0);
    127     splay(next, last);
    128     if(t[t[next].ch[0]].cnt > 1)
    129     {
    130         t[t[next].ch[0]].cnt--;
    131         splay(t[next].ch[0], 0);
    132     }
    133     else t[next].ch[0] = 0;
    134 }
    135 int main()
    136 {
    137     int n, x, y;
    138     Insert(-INF);
    139     Insert(INF);
    140     scanf("%d", &n);
    141     while(n--)
    142     {
    143         scanf("%d%d", &x, &y);
    144         if(x == 1)Insert(y);
    145         if(x == 2)delet(y);
    146         if(x == 3)printf("%d
    ", get_rank(y)- 1);//排名减一是因为要减去负无穷这个数
    147         if(x == 4)printf("%d
    ", kth(y + 1));//排名是y+1 因为加上负无穷这个数
    148         if(x == 5)printf("%d
    ", t[get_pre(y, 0)].val);
    149         if(x == 6)printf("%d
    ", t[get_pre(y, 1)].val);
    150     }
    151     return 0;
    152 }
  • 相关阅读:
    Mvc5+Ef 6.0入门开发随笔(2.MVC的简单创建与使用图文详解)
    转载:CSDN mvc ef 的简单增删改查操作
    插件
    Jmeter-后置处理器--json提取器
    jmeter的几种参数化方式
    Python--变量命名规范
    Python--对list、tuple、dict的操作
    Python--列表中字符串按照某种规则排序的方法
    Python--遍历文件夹下所有文件和目录的方法(os.walk(rootdir)函数返回一个三元素元祖)
    Python--递归函数实现:多维嵌套字典数据无限遍历
  • 原文地址:https://www.cnblogs.com/fzl194/p/9672354.html
Copyright © 2011-2022 走看看