博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj_2104K-th Number
阅读量:4956 次
发布时间:2019-06-12

本文共 3257 字,大约阅读时间需要 10 分钟。

K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 31646   Accepted: 9771
Case Time Limit: 2000MS

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 10
9 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 31 5 2 6 3 7 42 5 34 4 11 7 3

Sample Output

563
 
#include 
#include
#include
#include
using namespace std;#pragma warning(disable : 4996)const int MAXN = 100010;#define mid ((l + r) >> 1)int t[20][MAXN],sum[20][MAXN];int as[MAXN];//以下为查找区间第k小划分树void build(int p,int l,int r){ int lm = 0, i, ls = l, rs = mid + 1;//lm表示应被放入左子树且与中位数相等的数有多少个,ls为左子树的起始位置,rs为右子树的起始位置 for(i = mid; i >= l; i--) //求lm { if(as[i] == as[mid]) { lm++; } else { break; } } for(i = l; i <= r; i++) { if(i == l)//这里要特殊讨论 { sum[p][i] = 0; } else { sum[p][i] = sum[p][i-1]; } if(t[p][i] == as[mid])//若与中位数相等则判断是否应该被放入左子树 { if(lm != 0) { lm--; sum[p][i]++; t[p+1][ls++] = t[p][i]; } else { t[p+1][rs++] = t[p][i]; } } else if(t[p][i] < as[mid])//查找区间第K大即为> { sum[p][i]++; t[p+1][ls++]=t[p][i]; } else { t[p+1][rs++] = t[p][i]; } } if(l==r) { return; } build(p + 1, l, mid); build(p + 1, mid + 1, r);}int query(int p, int l, int r, int ql, int qr, int k){ int s, ss;//s表示l到ql-1的区间内放入左子树的个数,ss表示区间[ql,qr]被放入左子树的个数 if(l == r)//找到所求的数 { return t[p][l]; } if(ql == l) { s = 0, ss = sum[p][qr]; } else { s = sum[p][ql-1], ss = sum[p][qr] - s; } if(k<=ss)//要找的数在左子树中 { return query(p + 1, l, mid, l + s, l + sum[p][qr] - 1, k); } else//要找的数在右子树中 { return query(p + 1, mid + 1, r, mid + 1 - l + ql - s, mid + 1 - l + qr - sum[p][qr], k - ss); }}int main(){ freopen("in.txt", "r", stdin); int n, m, x, y, z; scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &as[i]); t[0][i] = as[i]; } sort(as + 1, as + n + 1); build(0, 1, n); while (m--) { scanf("%d %d %d", &x, &y, &z); printf("%d\n", query(0, 1, n, x, y, z)); } return 0;}

转载于:https://www.cnblogs.com/lgh1992314/archive/2013/05/28/5835014.html

你可能感兴趣的文章
js 基础拓展
查看>>
SpringBoot访问html访问不了的问题
查看>>
{width=200px;height=300px;overflow:hidden}
查看>>
C#生成随机数
查看>>
CSS基础学习 20.CSS媒体查询
查看>>
2019春季第十一周作业
查看>>
洛谷P4591 [TJOI2018]碱基序列 【KMP + dp】
查看>>
iOS CoreData介绍和使用(以及一些注意事项)
查看>>
OS笔记047代理传值和block传值
查看>>
Android应用程序与SurfaceFlinger服务的连接过程分析
查看>>
coco2dx服务器简单例子
查看>>
Java回顾之多线程
查看>>
sqlite
查看>>
机电行业如何进行信息化建设
查看>>
Windows Azure Platform Introduction (4) Windows Azure架构
查看>>
【转】chrome developer tool 调试技巧
查看>>
mahout运行测试与kmeans算法解析
查看>>
互相给一巴掌器
查看>>
Android SDK环境变量配置
查看>>
VM10虚拟机安装图解
查看>>