zoukankan      html  css  js  c++  java
  • poj2104 K-th Number

    划分树。

    实际上相当于把数列归并排序的过程用树形结构储存起来,并通过一个辅助二位数组记录数的每一层上的每一个元素被划分到子树的情况(划分到左子树

    或右子树)。

    归并排序具有稳定性,这也是能够准确查询k-th元素的关键。

    通过辅助数组在树形结构中不断判断第k个元素属于哪个子树哪个区间,最终找到此元素。

    http://poj.org/problem?id=2104

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const int maxn = 1e5 + 10;
     8 const int maxd = 22;
     9 
    10 int tree[maxd][maxn], left[maxd][maxn];
    11 int s[maxn];
    12 int n, m, l, r, k;
    13 
    14 void build(int d, int l, int r){
    15     if(r - l < 2) return;
    16     int mid = (l + r) >> 1;
    17     int left_mid = mid - l;
    18     for(int i = l; i < r; i++) if(tree[d][i] < s[mid]) left_mid--;
    19     int ls = l, rs = mid;
    20     for(int i = l; i < r; i++){
    21         int flag = 1;
    22         if(tree[d][i] < s[mid])    tree[d + 1][ls++] = tree[d][i];
    23         else if(tree[d][i] == s[mid] && left_mid) tree[d + 1][ls++] = tree[d][i], --left_mid;
    24         else tree[d + 1][rs++] = tree[d][i], flag = 0;
    25         left[d][i + 1] = left[d][i] + flag;
    26     }
    27     build(d + 1, l, mid);
    28     build(d + 1, mid, r);
    29 }
    30 
    31 int query(int k, int l, int r, int d, int L, int R){
    32     //find the k-th number in range[l, r) within tree of depth d
    33     if(r - l < 2) return tree[d][l];
    34     int Ll1 = left[d][l] - left[d][L];
    35     //num of elements in range [L, l) divided into left-subtree
    36     int Lr1 = left[d][r] - left[d][L];
    37     int Ll2 = l - L - (left[d][l] - left[d][L]);
    38     int Lr2 = r - L - (left[d][r] - left[d][L]);
    39     int mid = (L + R) >> 1;
    40     int cnt_left = Lr1 - Ll1;
    41     if(cnt_left >= k) return query(k, L + Ll1, L + Lr1, d + 1, L, mid);
    42     else return query(k - cnt_left, mid + Ll2, mid + Lr2, d + 1, mid, R);
    43 }
    44 
    45 int main(){
    46     while(~scanf("%d%d", &n, &m)){
    47         for(int i = 0; i < n; i++){
    48             scanf("%d", &s[i]);
    49             tree[0][i] = s[i];
    50         }
    51         sort(s, s + n);
    52         for(int i = 0; i < maxd; i++) left[i][0] = 0;
    53         build(0, 0, n);
    54         for(int i = 0; i < m; i++){
    55             scanf("%d%d%d", &l, &r, &k);
    56             int ans = query(k, l - 1, r, 0, 0, n);
    57             printf("%d
    ", ans);
    58         }
    59     }
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    Python 使用 environs 库来更好地定义环境变量
    五分钟带你了解map、reduce和filter
    部署React前端和Django后端的3种方法
    marshmallow库更优雅的数据转换
    利用 attrs 和 cattrs 两个库实现 Python 面向对象编程
    parse库,更友好的格式化数据提取方案
    python之prettytable模块格式化打印
    使用类型注解让 Python 代码更易读
    jksj算法训练营-第三课01 数组、链表、跳表
    linux安装java步骤
  • 原文地址:https://www.cnblogs.com/astoninfer/p/4752718.html
Copyright © 2011-2022 走看看