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

    Description

    You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment.
    That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?"
    For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

    Input

    The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000).
    The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.
    The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

    Output

    For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

    Sample Input

    7 3
    1 5 2 6 3 7 4
    2 5 3
    4 4 1
    1 7 3

    Sample Output

    5
    6
    3

     题解:这题有很多种写法。归并树,故名思义,就是用树形结构来存归并排序的相关信息。这里用到的是线段树,因为归并排序划分子序列的方式和线段树划分子序列的方式相同,

    既划分(l,r)区间,子区间分别为(l,mid)和(mid+1,r)。树的每个节点对应了一段区间,存的是这段区间排好序的序列。如何排序?看归并树的名字,在合并子区间的时候

    用上归并排序就行了,既  Pushup函数  。由于合并是自底向上的,所以第一层就是整个序列排好序的样子。而查询就是枚举第一层序列的数看是否满足要求,因为有序,二分就有

    了用武之地。对于要查询的区间,在归并树中有着对应的节点(节点就是一段区间),且已经排好序。那么用lower_bound可以方便的求出在这个区间有多少个小于key的数。

    注意:实现的时候要仔细了解lower_bound的特点。统计的是小于key的个数。

     1 #pragma warning(disable:4996)
     2 #include<bitset>
     3 #include<string>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<iostream>
     7 #include<algorithm>
     8 using namespace std;
     9 typedef long long ll;
    10 
    11 const int maxn = 100005;
    12 
    13 int n, q;
    14 int Tree[20][maxn], a[maxn];
    15 
    16 void Pushup(int l, int mid, int r, int deep) {
    17     int i = l, j = mid + 1, k = l;
    18     while (i <= mid && j <= r) {
    19         if (Tree[deep + 1][i] <= Tree[deep + 1][j])
    20             Tree[deep][k++] = Tree[deep + 1][i++];
    21         else
    22             Tree[deep][k++] = Tree[deep + 1][j++];
    23     }
    24     while (i <= mid) Tree[deep][k++] = Tree[deep + 1][i++];
    25     while (j <= r) Tree[deep][k++] = Tree[deep + 1][j++];
    26 }
    27 
    28 void Build(int l, int r, int deep) {
    29     if (l == r) {
    30         Tree[deep][l] = a[l];
    31         return;
    32     }
    33     int mid = (l + r) >> 1;
    34     Build(l, mid, deep + 1);
    35     Build(mid + 1, r, deep + 1);
    36     Pushup(l, mid, r, deep);
    37 }
    38 
    39 
    40 int Query(int L, int R, int l, int r, int k, int deep) {
    41     if (l > R || r < L) return 0;
    42     if (l >= L && r <= R) return lower_bound(&Tree[deep][l], &Tree[deep][r] + 1, k) - &Tree[deep][l];  //用lower_bound时注意啦!!!!!!
    43 
    44     int mid = (l + r) >> 1;
    45     return  Query(L, R, l, mid, k, deep + 1) + Query(L, R, mid + 1, r, k, deep + 1);
    46 
    47 }
    48 
    49 
    50 int Solve(int L, int R, int k) {
    51     int l = 1, r = n + 1;          //二分。。。。。别写挂了
    52     for (int i = 1; i <= 30; i++) {
    53         int mid = (l + r) >> 1;
    54         int cnt = Query(L, R, 1, n, Tree[1][mid], 1);
    55         if (cnt <= k) l = mid;
    56         else r = mid; 
    57     }
    58     return Tree[1][l];
    59 }
    60 
    61 int main()
    62 {
    63     while (scanf("%d%d", &n, &q) != EOF) {
    64         for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    65         Build(1, n, 1);
    66 
    67         for (int i = 1; i <= q; i++) {
    68             int l, r, k;
    69             scanf("%d%d%d", &l, &r, &k);
    70             printf("%d
    ", Solve(l, r, k - 1));
    71         }
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    boost库的使用介绍
    《架构实战软件架构设计的过程》
    常用开发命令
    《项目管理最佳实践案例剖析》
    From Live Writer
    希望实现的程序
    正在进行调试的Web服务器进程已由Internet信息服务(IIS)终止。可以通过在IIS中配置应用程序池Ping设置来避免这一问题。有关更多详细信息,请参见“帮助”
    请确保此代码文件中定义的类与“inherits”属性匹配
    更改IE默认源代码编辑器
    MS的.net源码地址
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/8747378.html
Copyright © 2011-2022 走看看