zoukankan      html  css  js  c++  java
  • 普通平衡树的基础操作

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    普通平衡树的常规操作模板

    普通平衡树可以实现求排名这样的问题,输入很多同学的成绩,求89分排在多少位,或者第几位是多少名

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    main函数

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 struct opt { int num, value; };
     6 struct Segtree { int value; };
     7 opt Data[100010];
     8 Segtree segtree[400010];
     9 vector<int>vt;
    10 const int INF = 2147483647;
    11 int index;
     1 int main()
     2 {
     3     ios::sync_with_stdio(false);
     4     cin.tie(0);
     5     int n;
     6     cin >> n;
     7     for (int i = 0; i < n; i++)
     8     {
     9         cin >> Data[i].num >> Data[i].value;
    10         if (Data[i].num !=4)
    //只有4操作是输入排名,而像5和6这样子的操作输入的x可能不在原排列内,即成绩有70 85,现在我要求80的前驱,所以要给80留个位子
    //3操作比如成绩有70 85,我想知道如果我成绩80能排多少名,所以也要给80留个位置,不过80的value为0,不影响
    11 { 12 vt.push_back(Data[i].value); 13 } 14 } 15 discretization(); 16 for (int i = 0; i < n; i++) 17 { 18 if (Data[i].num == 1) Tree_insert(1, 1, index, get_pos(Data[i].value), 1);//get_pos是为了找到离散化后映射的那个数 19 else if (Data[i].num == 2) Tree_insert(1, 1, index, get_pos(Data[i].value), -1); 20 else if (Data[i].num == 3) cout << Get_ranked(1, 1, index, get_pos(Data[i].value)) << endl; 21 else if (Data[i].num == 4) cout << Get_kth(1, 1, index, Data[i].value) << endl; 22 else if (Data[i].num == 5) cout << Get_pre(Data[i].value) << endl; 23 else if (Data[i].num == 6)cout << Get_succeed(Data[i].value) << endl; 24 } 25 return 0; 26 }

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    离散化

    离散化的目的是为了找出对应值来减少空间

    比如输入的四个数为10 500 1000 1000000000

    没有必要在10-1000000000之中找,而是让1对应10,2对应500,3对应1000,4对应1000000000这样

    1 void discretization()
    2 {
    3     vt.push_back(-INF);//为了让vector中所要操作的数从1开始而不是0开始,先加入一个最小值
    4     sort(vt.begin(), vt.end());
    5     vt.erase(unique(vt.begin(), vt.end()), vt.end());
    //unique能把vector里相同的数提到后面,并返回不重复的排序最后的位置,我们把这个位置到vector末尾的都清掉
    //即把那些重复的都清掉,只留一个
    6 index = vt.size() - 1;//一共有几个不相同的数 7 return; 8 }

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    求离散化之后的值

    1 int get_pos(int value)//为了得到这个数在vector里排第几,利用该数的位置求
    2 {
    3     return lower_bound(vt.begin(), vt.end(), value)-vt.begin();返回这个值的第一个数的位置再减去开头的(可能有很多重复的,如有四个2,取第一个2)
    4 }

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    插入和删除

     1 void Tree_insert(int root, int left, int right, int pos, int k)//一般k只取正负1,表示同样的数有几个,插入就k=1,删除就k=-1
     2 {
     3     if (left == right) {
     4         segtree[root].value += k; return;//到了最底层,找到叶子结点,就可以加或减1了
     5     }
     6     int mid = (left + right) >> 1;//利用二分法找要插入的点的位置
     7     if (pos <= mid) Tree_insert(root << 1, left, mid, pos, k);//要插入的数在mid的左侧
     8     else Tree_insert(root << 1 | 1, mid + 1, right, pos, k);
     9     segtree[root].value = segtree[root << 1].value + segtree[root << 1 | 1].value;//递归更新树
    10     return;
    11 }

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     查询x数的排名(即成绩为x,排多少)

    1 int Get_ranked(int root, int left, int right, int pos)
    2 {
    3     if (left == right) return 1;//返回1是因为题目要求要算入自己
    4     int mid = (left + right) >> 1;
    5     if (pos <= mid) return Get_ranked(root << 1, left, mid, pos);
    6     return segtree[root << 1].value + Get_ranked(root << 1 | 1, mid + 1, right, pos);//左侧的排名也要加上
    7 }

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    查询排名为k的数的值

    1 int Get_kth(int root, int left, int right, int k)//在left和right中找排名为k的值
    2 {
    3     if (left == right) return vt[left];//注意left是离散化对应的值,要返回它原来离散化之前的值
    4         int mid = (left + right) >> 1;
    5     if (k <= segtree[root << 1].value) return Get_kth(root << 1, left, mid, k);
    6     return Get_kth(root << 1 | 1, mid + 1, right, k-segtree[root<<1].value);//比如要在1-7找排名为6的数,那么就只要在5-7里找排名为2的数
    7 }

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    求前驱的值

    1 int Get_pre(int k)
    2 {
    3     return Get_kth(1, 1, index, Get_ranked(1, 1, index, get_pos(k))-1);//先求出所给值的排名,那么他的排名-1就是前驱值的排名,再根据排名求原值
    4 }

    ---------------------------------------------------------   -----------------------------------------------------------------------------------------------------------------------------

    求后继的值

    1 int Get_succeed(int k)
    2 {
    3     return Get_kth(1, 1, index, Get_ranked(1, 1, index, get_pos(k+1)));
    4 }

    ---------------------------------------------------------  ------------------------------------------------------------------------------------------------------------------------------

    完整代码

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 struct opt { int num, value; };
     6 struct Segtree { int value; };
     7 opt Data[100010];
     8 Segtree segtree[400010];
     9 vector<int>vt;
    10 const int INF = 2147483647;
    11 int index;
    12 void discretization()
    13 {
    14     vt.push_back(-INF);
    15     sort(vt.begin(), vt.end());
    16     vt.erase(unique(vt.begin(), vt.end()), vt.end());
    17      index = vt.size() - 1;
    18     return;
    19 }
    20 int get_pos(int value)
    21 {
    22     return lower_bound(vt.begin(), vt.end(), value)-vt.begin();
    23 }
    24 void Tree_insert(int root, int left, int right, int pos, int k)
    25 {
    26     if (left == right) {
    27         segtree[root].value += k; return;
    28     }
    29     int mid = (left + right) >> 1;
    30     if (pos <= mid) Tree_insert(root << 1, left, mid, pos, k);
    31     else Tree_insert(root << 1 | 1, mid + 1, right, pos, k);
    32     segtree[root].value = segtree[root << 1].value + segtree[root << 1 | 1].value;
    33     return;
    34 }
    35 int Get_ranked(int root, int left, int right, int pos)
    36 {
    37     if (left == right) return 1;
    38     int mid = (left + right) >> 1;
    39     if (pos <= mid) return Get_ranked(root << 1, left, mid, pos);
    40     return segtree[root << 1].value + Get_ranked(root << 1 | 1, mid + 1, right, pos);
    41 }
    42 int Get_kth(int root, int left, int right, int k)
    43 {
    44     if (left == right) return vt[left];
    45         int mid = (left + right) >> 1;
    46     if (k <= segtree[root << 1].value) return Get_kth(root << 1, left, mid, k);
    47     return Get_kth(root << 1 | 1, mid + 1, right, k-segtree[root<<1].value);
    48 }
    49 int Get_pre(int k)
    50 {
    51     return Get_kth(1, 1, index, Get_ranked(1, 1, index, get_pos(k))-1);
    52 }
    53 int Get_succeed(int k)
    54 {
    55     return Get_kth(1, 1, index, Get_ranked(1, 1, index, get_pos(k+1)));
    56 }
    57 int main()
    58 {
    59     ios::sync_with_stdio(false);
    60     cin.tie(0);
    61     int n;
    62     cin >> n;
    63     for (int i = 0; i < n; i++)
    64     {
    65         cin >> Data[i].num >> Data[i].value;
    66         if (Data[i].num !=4)
    67         {
    68             vt.push_back(Data[i].value);
    69         }
    70     }
    71     discretization();
    72     for (int i = 0; i < n; i++)
    73     {
    74         if (Data[i].num == 1) Tree_insert(1, 1, index, get_pos(Data[i].value), 1);
    75         else if (Data[i].num == 2) Tree_insert(1, 1, index, get_pos(Data[i].value), -1);
    76         else if (Data[i].num == 3) cout << Get_ranked(1, 1, index, get_pos(Data[i].value)) << endl;
    77         else if (Data[i].num == 4) cout << Get_kth(1, 1, index, Data[i].value) << endl;
    78         else if (Data[i].num == 5) cout << Get_pre(Data[i].value) << endl;
    79         else if (Data[i].num == 6)cout << Get_succeed(Data[i].value) << endl;
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    使用Azure进行自动化机器学习
    关于ML.NET v1.0 RC的发布说明
    关于ML.NET v0.8的发布说明
    使用ML.NET + Azure DevOps + Azure Container Instances打造机器学习生产化
    使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET机器学习模型
    neo4j 数据库迁移
    ubuntu1604 搜狗输入法安装
    Chrome 键盘快捷键
    Ubuntu Cleaner清理工具
    bash 数组
  • 原文地址:https://www.cnblogs.com/Knightero/p/12681875.html
Copyright © 2011-2022 走看看