【POJ2104】【整体二分+树状数组】区间第k大

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

Hint

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

Source

Northeastern Europe 2004, Northern Subregion

【分析】

比上一道题目还简单..

  1 /*
  2 宋代郑思肖
  3 《画菊》
  4 花开不并百花丛,独立疏篱趣未穷。
  5 宁可枝头抱香死,何曾吹落北风中。
  6 */
  7 #include <iostream>
  8 #include <cstdio>
  9 #include <algorithm>
 10 #include <cstring>
 11 #include <vector>
 12 #include <utility>
 13 #include <iomanip>
 14 #include <string>
 15 #include <cmath>
 16 #include <queue>
 17 #include <assert.h>
 18 #include <map>
 19 #include <ctime>
 20 #include <cstdlib>
 21 #include <stack>
 22 #define LOCAL
 23 const int MAXN = 100000 + 10;
 24 const int MAXM = 5000 + 10;
 25 const int INF = 0x7fffffff;
 26 const int SIZE = 450;
 27 const int maxnode =  250005 + 10;
 28 using namespace std;
 29 typedef long long ll;
 30 using namespace std;
 31 struct DATA{
 32        int val, x;//x代表位置
 33        bool operator < (const DATA &b)const{
 34             return val < b.val;
 35        }
 36 }data[MAXN];
 37 struct QUESTION{
 38        int l, r;
 39        int k;
 40 }q[MAXM];
 41 int c[MAXN], id[MAXN], Ans[MAXN];
 42 int tmp[MAXN];
 43 bool mark[MAXN];
 44 int Max = -INF, Min = INF, pos, n, m;
 45 //树状数组
 46 inline int lowbit(int x){return x&-x;}
 47 int sum(int x){
 48     int tmp = 0;
 49     while (x > 0){
 50           tmp += c[x];
 51           x -= lowbit(x);
 52     }
 53     return tmp;
 54 }
 55 void add(int x, int val){
 56      while (x <= n){
 57            c[x] += val;
 58            x += lowbit(x);
 59      }
 60      return;
 61 }
 62
 63 void init(){
 64      memset(mark, 0, sizeof(mark));
 65      memset(c, 0, sizeof(c));
 66      scanf("%d%d", &n, &m);
 67      for (int i = 1; i <= n; i++){
 68          scanf("%d", &data[i].val);
 69          data[i].x = i;
 70          Max = max(Max, data[i].val);
 71          Min = min(Min, data[i].val);
 72      }
 73      //排序
 74      sort(data + 1, data + 1 + n);
 75 }
 76 void solve(int l, int r, int L, int R){
 77       if (l > r || L == R) return;
 78       int mid = (L + R) >> 1;
 79       while (data[pos + 1].val <= mid && pos < n){
 80             add(data[pos + 1].x, 1);
 81             pos++;
 82       }
 83       while (data[pos].val > mid){
 84             add(data[pos].x, -1);
 85             pos--;
 86       }
 87       int cnt = 0;//记录找到答案的回答个数
 88       for (int i = l; i <= r; i++){
 89           if (sum(q[id[i]].r) - sum(q[id[i]].l - 1) > q[id[i]].k - 1){
 90              Ans[id[i]] = mid;
 91              mark[i] = 1;
 92              cnt++;
 93           }else mark[i] = 0;
 94       }
 95       int l1 = l, l2 = l + cnt;
 96       for (int i = l; i <= r; i++)
 97       if (mark[i]) tmp[l1++] = id[i];
 98       else tmp[l2++] = id[i];
 99
100       for (int i = l; i <= r; i++) id[i] = tmp[i];
101       solve(l, l1 - 1, L, mid);
102       solve(l1, l2 - 1, mid + 1, R);
103 }
104 void work(){
105      pos = 0;//初始化即data中的下标
106      for (int i = 1; i <= m; i++){
107          scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].k);
108      }
109      for (int i = 1; i <= m; i++) id[i] = i;
110      solve(1, m, Min, Max + 1);
111      for (int i = 1; i <= m; i++) printf("%d\n", Ans[i]);
112 }
113
114 int main(){
115
116     init();
117     work();
118     return 0;
119 }

时间: 2024-10-29 19:06:19

【POJ2104】【整体二分+树状数组】区间第k大的相关文章

【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改

题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. 输入 第一行N,M接下来M行,每行形如1 a b c或2 a b c 输出 输出每个询问的结果 样例输入 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 样例输出 1 2 1 题解 整体二分+树状数组区间修改 当年naive的树套树题解 前两天由于要

【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 HINT

【转载】【树状数组区间第K大/小】

原帖:http://www.cnblogs.com/zgmf_x20a/archive/2008/11/15/1334109.html 回顾树状数组的定义,注意到有如下两条性质: 一,c[ans]=sum of A[ans-lowbit(ans)+1 ... ans];二,当ans=2^k时, c[ans]=sum of A[1 ... ans]; 下面说明findK(k)如何运作:1,设置边界条件ans,ans'<maxn且cnt<=k:2,初始化cnt=c[ans],其中ans=2^k且k

Permutation UVA - 11525(值域树状数组,树状数组区间第k大(离线),log方,log)

Permutation UVA - 11525 看康托展开 题目给出的式子(n=s[1]*(k-1)!+s[2]*(k-2)!+...+s[k]*0!)非常像逆康托展开(将n个数的所有排列按字典序排序,并将所有排列编号(从0开始),给出排列的编号得到对应排列)用到的式子.可以想到用逆康托展开的方法.但是需要一些变化: for(i=n;i>=1;i--) { s[i-1]+=s[i]/(n-i+1); s[i]%=(n-i+1); } 例如:n=3时,3=0*2!+0*1!+3*0!应该变为3=1

【bzoj2527】[Poi2011]Meteors 整体二分+树状数组

题目描述 有N个成员国.现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会下陨石雨.BIU已经预测了接下来K场陨石雨的情况.BIU的第i个成员国希望能够收集Pi单位的陨石样本.你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石. 输入 第一行是两个数N,M. 第二行有M个数,第i个数Oi表示第i段轨道上有第Oi个国家的太空站. 第三行有N个数,第i个数Pi表示第i个国家希望收集的陨石数量. 第四行有一个

【BZOJ-2527】Meteors 整体二分 + 树状数组

2527: [Poi2011]Meteors Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 831  Solved: 306[Submit][Status][Discuss] Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colo

HDU 5249 离线树状数组求第k大+离散化

KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1160    Accepted Submission(s): 488 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的

hdu 2985 The k-th Largest Group 树状数组求第K大

The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8353   Accepted: 2712 Description Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to g

bzoj 2527 Meteors - 整体二分 - 树状数组

Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colonisation due to strange meteor showers, which on the other hand make it an exceptionally interesting object of st