18.10.22 POJ 2104 K-th Number(二分+线段树+离散化)

描述

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.输入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).输出For each question output the answer to it --- the k-th number in sorted a[i...j] segment

.样例输入

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

样例输出

5
6
3

提示

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

来源

Northeastern Europe 2004, Northern Subregion

  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <stack>
  5 #include <string>
  6 #include <math.h>
  7 #include <queue>
  8 #include <stdio.h>
  9 #include <string.h>
 10 #include <vector>
 11 #include <fstream>
 12 #include <set>
 13 #include<map>
 14 #define l(rt) rt*2
 15 #define r(rt) rt*2+1
 16 #define mid(l,r) (l+r)/2
 17 
 18 using namespace std;
 19 const int maxn = 100005;
 20 int n, m,num[maxn],b[maxn];
 21 struct number {
 22     int val, id;
 23     bool operator <(number a) {
 24         return val < a.val;
 25     }
 26 };
 27 number _num[maxn];
 28 struct node {
 29     vector<int> va;
 30     int l, r;
 31 }tree[4*maxn];
 32 
 33 void build(int rt,int l,int r) {
 34     tree[rt].l = l, tree[rt].r = r;
 35     if (l == r)
 36     {
 37         tree[rt].va.push_back(b[l]);
 38         return;
 39     }
 40     build(l(rt), l, mid(l, r));
 41     build(r(rt), mid(l, r) + 1, r);
 42     int i = 0, j = 0, sizer = tree[r(rt)].va.size(), sizel = tree[l(rt)].va.size();
 43     while (i != sizel || j != sizer) {
 44         if (i != sizel && j != sizer) {
 45             if (tree[l(rt)].va[i] <= tree[r(rt)].va[j])
 46                 tree[rt].va.push_back(tree[l(rt)].va[i++]);
 47             else
 48                 tree[rt].va.push_back(tree[r(rt)].va[j++]);
 49         }
 50         if (i == sizel)
 51             while (j != sizer)
 52                 tree[rt].va.push_back(tree[r(rt)].va[j++]);
 53         if (j == sizer)
 54             while (i != sizel)
 55                 tree[rt].va.push_back(tree[l(rt)].va[i++]);
 56     }
 57     return;
 58 }
 59 
 60 int query(int rt, int l, int r, int x) {//小于等于x的个数
 61     if (tree[rt].l == l && tree[rt].r == r)
 62         return upper_bound(tree[rt].va.begin(), tree[rt].va.end(), x)-tree[rt].va.begin();
 63     int midn = mid(tree[rt].r, tree[rt].l);
 64     if (l > midn)
 65         return query(r(rt), l, r, x);
 66     else if (r <= midn)
 67         return query(l(rt), l, r, x);
 68     else
 69         return query(l(rt), l, midn, x) + query(r(rt), midn + 1, r, x);
 70 }
 71 
 72 void solve(int l, int r, int k) {
 73     int res;
 74     int s = 1, e = n+1;
 75     while (s<e) {
 76         int x = s + (e - s) / 2;
 77         res = query(1, l, r, x);
 78         if (res >= k)e = x;
 79         else
 80             s = x + 1;
 81     }
 82     printf("%d\n", num[s]);
 83 }
 84 
 85 void init() {
 86     scanf("%d%d", &n, &m);
 87     for (int i = 1; i <= n; i++)
 88     {
 89         scanf("%d", &num[i]);
 90         _num[i].val = num[i];
 91         _num[i].id = i;
 92     }
 93     sort(_num + 1, _num + n + 1);
 94     for (int i = 1; i <= n; i++) 
 95         b[_num[i].id] = i;
 96     build(1,1, n);
 97     sort(num + 1, num + n + 1);
 98     while (m--) {
 99         int x, y, k;
100         scanf("%d%d%d", &x, &y, &k);
101         solve(x, y, k);
102     }
103 }
104 
105 int main()
106 {
107     init();
108     return 0;
109 }
View Code

每个星期一都是意识模糊的一天

查了下,还有一种做法是主席树,很有意思,准备之后看一下

思路:

二分查找答案使得尝试的这个数x在所考察区间内,正好有k个数字小于等于它

线段树的作用是得到区间内小于等于x的数的个数

离散化是加快速度

 

这个实现超烂,又臭又长

posted @ 2018-10-22 20:10  TobicYAL  阅读(284)  评论(0编辑  收藏  举报