划分树 poj2104 hdu5249
Posted lcchuguo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了划分树 poj2104 hdu5249相关的知识,希望对你有一定的参考价值。
KPI
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 616 Accepted Submission(s): 261
每组数据第一行有一个
接下来有n行。每一行有3种形式
"in x": 代表重要值为
"out": 代表服务拉取了管道头部的请求。
"query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,假设当前管道内有m条请求, 我想知道。升序排序后第
为了让题目简单,全部的x都不同。而且假设管道内没有值。就不会有"out"和"query"操作。
Case #i:
然后每一次"query"。输出当前管道内重要值的中间值。
6 in 874 query out in 24622 in 12194 query
Case #1: 874 24622
Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 41138 | Accepted: 13447 | |
Case Time Limit: 2000MS |
Description
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 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
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.
这两题都 要求子区间的第k大数,假设用快排之后,再查,复杂度太大。不能过,就要用到划分树了,划分树。事实上,就是线段树的
一个变种了,当然,这样做查询是lg(n)级别,建树是n * lg(n),再加上一次快排,也是n * lg(n),差点儿相同就能够过了!
先来看看划分树,我们在线段树的基础上,假设每一个结点都保存了。当前子段向左子树走的个数。假设,查询的k要小于,查询段向左走的个数,自然,我们向左子树就能够查到结果。假设,k>向左走的个数,当然要向右找k-midcount个数,区间的变换。我们能够
推一下向左走就是l + scount, l + ecount - 1。向右走就是mid + 1 + s - l - scount, mid + 1 + e - l - ecount,当中scount就是s之前向左走的个数。 ecount,就是e之前向左走的个数。
上核心代码
#define MID(a,b) (((a)+(b))>>1) #define N 100050 int num[20][N], val[20][N]; //第i层,向左包含自已,向左子树的个数,当前的值 int pri[N], sorted[N]; //原始和排序后的数列 char str[20]; void build(int l, int r, int layer){ if (l >= r){ return; } int mid = MID(l, r); int ql = l, qr = mid + 1, leftCount = mid, eqCount = 0; for (int i = l; i <= r; i++) leftCount -= val[layer][i] < sorted[mid]; for (int i = l; i <= r; i++){ if (i == l){ num[layer][i] = 0; } else{ num[layer][i] = num[layer][i - 1]; } if (val[layer][i] < sorted[mid]){ num[layer][i]++; val[layer + 1][ql++] = val[layer][i]; } else if (val[layer][i] > sorted[mid]){ val[layer + 1][qr++] = val[layer][i]; } else { if (eqCount < leftCount){ eqCount++; num[layer][i]++; val[layer + 1][ql++] = val[layer][i]; } else { val[layer + 1][qr++] = val[layer][i]; } } } build(l, mid, layer + 1); build(mid + 1, r, layer + 1); } //在layer层l到r间,找s-e之间的第k大数 int query(int l, int r, int layer, int s, int e, int k){ if (l >= r || s >= e){ return val[layer][s]; } int scount, ecount, mid = MID(l, r); if (s == l){ scount = 0, ecount = num[layer][e]; } else { scount = num[layer][s - 1], ecount = num[layer][e]; } int midcount = ecount - scount; if (k <= midcount){ return query(l, mid, layer + 1, l + scount, l + ecount - 1, k); } else { return query(mid + 1, r, layer + 1, mid + 1 + s - l - scount, mid + 1 + e - l - ecount, k - midcount); } } int main() { int tcase, tcasenum = 0; int n, k, q, s, e, begin = 1, nn, qcount, m; while (S2(n, m) != EOF) { FI(n){ S(val[0][i+1]); } FI(n){ sorted[i + 1] = val[0][i + 1]; } sort(sorted + 1, sorted + n + 1); build(1, n, 0); FI(m){ S2(s, e); S(q); Prn(query(1, n, 0, s,e,q)); } } return 0; }
以上是关于划分树 poj2104 hdu5249的主要内容,如果未能解决你的问题,请参考以下文章