POJ2104 K-th Number 【归并树】

K-th Number

Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 38379   Accepted: 12480
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 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

题意:给定一个包含n个不同数的数列a1, a2, ..., an 和m个三元组表示的查询。对于每个查询(i, j, k), 输出ai, ai+1, ... ,aj的升序排列中第k个数 。

题解:用线段树,每个节点维护一个区间并且保证内部升序,对于每次查询x,返回该区间小于x的数的个数。就这样不断二分,直到找到x为止。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>

#define maxn 100005
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;

vector<int> T[maxn << 2];
int N, Q;

void build(int l, int r, int rt) {
    if(l == r) {
        int val;
        scanf("%d", &val);
        T[rt].push_back(val);
        return;
    }

    int mid = (l + r) >> 1;

    build(lson);
    build(rson);

    T[rt].resize(r - l + 1); // Attention
    merge(T[rt<<1].begin(), T[rt<<1].end(), T[rt<<1|1].begin(), T[rt<<1|1].end(), T[rt].begin());
}

int query(int L, int R, int val, int l, int r, int rt) {
    if(L == l && R == r) {
        return upper_bound(T[rt].begin(), T[rt].end(), val) - T[rt].begin();
    }

    int mid = (l + r) >> 1;

    if(R <= mid) return query(L, R, val, lson);
    else if(L > mid) return query(L, R, val, rson);
    return query(L, mid, val, lson) + query(mid + 1, R, val, rson);
}

int main() {
    int a, b, c, k, left, right, mid;
    scanf("%d%d", &N, &Q);
    build(1, N, 1);
    while(Q--) {
        scanf("%d%d%d", &a, &b, &k);
        left = -1; right = N - 1;
        while(right - left > 1) { // binary search
            mid = (left + right) >> 1;
            c = query(a, b, T[1][mid], 1, N, 1);
            if(c >= k) right = mid;
            else left = mid;
        }
        printf("%d\n", T[1][right]);
    }
    return 0;
}
时间: 2024-08-26 18:48:18

POJ2104 K-th Number 【归并树】的相关文章

Poj 2104区间第k大(归并树)

题目链接 K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 36890 Accepted: 11860 Case Time Limit: 2000MS Description You are working for Macrohard company in data structures department. After failing your previous task about key ins

POJ 2014.K-th Number 区间第k大 (归并树)

K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 57543   Accepted: 19893 Case Time Limit: 2000MS Description You are working for Macrohard company in data structures department. After failing your previous task about key inse

【POJ2104】K-th Number——主席树

早上刷NOIP的题刷到有点烦就想学点新东西,然后.....一个早上就这样过去了QAQ.虽然主席树不是NOIP考点,但是...或许我能活到省选呢?(美好的幻想) 题目链接 题目的大意就是给定一个长度为n的区间,给出m个询问,每次询问一个区间[l,r]中第k小的树. 主席树(一种可持久化线段树)的入门题. 推荐一发学习资料:戳这里 感觉人家讲得很仔细了我也没什么讲的必要了...... 总算是学了一种可持久化树了,好像也没想象中那么难?这道题的重点在query函数方面,建议自己在纸上模拟一下建树和查询

【POJ2104】K-th Number 主席树?函数式线段树?可持久化线段树?……反正是其中一个

题意:区间静态第K大. 题解: 可持久化线段树. 可持久化线段树: 基本思想:我们维护插入每个节点后的线段树. 朴素写法(MLE+TLE)我们对于每次插入,都复制一棵线段树而后插入,这样保证了"可持久化". 但是显然,时间复杂度和空间复杂度都是n^2的.233. 所以有了优化写法:我们发现每次的插入只有logn个节点被改变,所以只需要这些点新建,其它点都指向原来版本的节点就好了. 空间复杂度nlogn. 然后这道题是区间第K大,对于区间[a,b],插入到b时的线段树,节点的size-(

归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k大 ,,,, 这个问题的通用算法是 划分树,, 说白一点就是把快速排序的中间结果存起来, 举个栗子 原数列 4 1 8 2 6 9 5 3 7 sorted 1 2 3 4 5 6 7 8 9 ........................... qs[0] 4 1 8 2 6 9 5 3 7 q

[POJ2104] K-th Number(归并树)

题目链接:http://poj.org/problem?id=2104 题意:略 最近想学一下分块,搜到了这道题.结果在<挑战>上另外看到了另外的用线段树做的算法.后来才知道,这种记录归并排序过程的树叫归并树.利用STL,非常好实现. 思路就是首先二分答案,拿着这个答案在归并树上找对应区间比这个数小的数的个数ret,找到==k的为止. 稍微对拍后,重新划了一下query的区间才发现是第40行写搓了.最近不刷题,码力下降了啊.. 1 #include <algorithm> 2 #i

POJ 2104 K-th Number(区间第k大数)(平方分割,归并树,划分树)

题目链接: http://poj.org/problem?id=2104 解题思路: 因为查询的个数m很大,朴素的求法无法在规定时间内求解.因此应该选用合理的方式维护数据来做到高效地查询. 如果x是第k个数,那么一定有 (1)在区间中不超过x的数不少于k个 (2)在区间中小于x的数有不到k个 因此,如果可以快速求出区间里不超过x的数的个数,就可以通过对x进行二分搜索来求出第k个数是多少. 接下来,我们来看一下如何计算在某个区间里不超过x个数的个数.如果不进行预处理,那么就只能遍历一遍所有元素.

POJ 2104 K-th Number(区间第k大数)(平方切割,归并树,划分树)

题目链接: http://poj.org/problem? id=2104 解题思路: 由于查询的个数m非常大.朴素的求法无法在规定时间内求解. 因此应该选用合理的方式维护数据来做到高效地查询. 假设x是第k个数,那么一定有 (1)在区间中不超过x的数不少于k个 (2)在区间中小于x的数有不到k个 因此.假设能够高速求出区间里不超过x的数的个数.就能够通过对x进行二分搜索来求出第k个数是多少. 接下来,我们来看一下怎样计算在某个区间里不超过x个数的个数. 假设不进行预处理,那么就仅仅能遍历一遍全

K-th Number 线段树(归并树)+二分查找

K-th Number 题意:给定一个包含n个不同数的数列a1, a2, ..., an 和m个三元组表示的查询.对于每个查询(i, j, k), 输出ai, ai+1, ... ,aj的升序排列中第k个数 . 题解:用线段树,每个节点维护一个区间并且保证内部升序,对于每次查询x,返回该区间小于x的数的个数.就这样不断二分,直到找到x为止. 线段树(归并树)+二分查找 1 #include <iostream> 2 #include <cstdio> 3 #include <

POJ2104-K-th Number-求区间第K大数(暴力or归并树or划分树)

题目链接:http://poj.org/problem?id=2104 题目意思很简单,就是给你一个序列,查询某区间第K大的数: 方法1:时间复杂度O(N*M):不支持更新操作,代码简单: 利用结构体排序,保留原数据的顺序. #include <stdio.h> #include <iostream> #include <algorithm> #define N 100000 using namespace std; /* 这个思路很好:时间复杂度O(n*m): 不过还