POJ2104 K-th Number[主席树]

K-th Number

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


document:

1.http://blog.csdn.net/metalseed/article/details/8045038

2.http://www.cnblogs.com/oyking/p/3230296.html

解决区间极值查询问题

主席树就是对每个前缀做了一个线段树

这样相当于处理了前缀和

提取一段区间,就是T[j]-T[i-1]

每棵线段树都按照[1,n]建树(保证链可以共用)

离散化后按照序列的顺序建树

T[i+1]和T[i]只有一条链不同,其他的可以共用

插入操作就是只把新链上的节点新建,其他的都用上一课树的

查询操作就是一个kth的过程,只不过要用两棵树的差值

PS:两种建树写法,貌似用引用比较快

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}
int n,m,mp[N],l,r,k;
struct data{
    int v,id;
    bool operator <(const data &r)const{return v<r.v;}
}a[N];
struct node{
    int lc,rc,size;
}t[N*20];
int cnt=0,root[N];
void insert(int num,int &x,int l,int r){//printf("ins %d %d %d\n",l,r,x);
    cnt++;
    t[cnt]=t[x];x=cnt;
    ++t[x].size;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(num<=mid) insert(num,t[x].lc,l,mid);
    else insert(num,t[x].rc,mid+1,r);
}
int ins(int num,int pre,int l,int r){
    int x=++cnt;
    t[x]=t[pre]; ++t[x].size;
    if(l==r) return x;
    int mid=(l+r)>>1;
    if(num<=mid) t[x].lc=ins(num,t[x].lc,l,mid);
    else t[x].rc=ins(num,t[x].rc,mid+1,r);
    return x;
}
int query(int i,int j,int l,int r,int k){
    if(l==r) return l;
    int ls=t[t[j].lc].size-t[t[i].lc].size;
    int mid=(l+r)>>1;
    if(k<=ls) return query(t[i].lc,t[j].lc,l,mid,k);
    else return query(t[i].rc,t[j].rc,mid+1,r,k-ls);
}

int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++) a[i].v=read(),a[i].id=i;
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++) mp[a[i].id]=i;

    for(int i=1;i<=n;i++){
        //root[i]=ins(mp[i],root[i-1],1,n);
        root[i]=root[i-1];
        insert(mp[i],root[i],1,n);
    }
    while(m--){
        l=read();r=read();k=read();
        printf("%d\n",a[query(root[l-1],root[r],1,n,k)].v);

    }
}
时间: 2024-10-16 06:22:30

POJ2104 K-th Number[主席树]的相关文章

【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-(

AcWing 255. 第K小数 (主席树写法)

区间k小数是主席树的模板题目,如果区间不包含,用莫队+权值线段树也能解 主席树是可持久化线段树,所为可持久化,就是每次只新增不一样的节点,而保留前面的版本,这样可以做到查询. 如果询问时1-r,那么直接主席树,询问的是l-r,就用到前缀和思想,具体看代码注释 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #inclu

poj2104 K-th Number 主席树入门;

题目链接:K-th Number 题解:我们先把数组离散离散化一下,然后先不考虑L,R的区间的关系,我们有一个棵线段树sum[]保存的是第几大到第几大出现的个数,这样我们想要询问这颗线段数的第k大是多少可以在log(n)次下就找到,但是区间的不同,一颗线段树是解决不了的,那我们如何得到L,R区间的sum数组呢?.我们可以建N棵线段树,第一棵树是空树,然后第一个数过来我们再建一课线段树在原来树的基础上,加上这个数对sum数组的贡献,这样从第一个到第N个建N棵线段树建好,我们可以发现sum[]有前缀

poj2104求区间第k小,静态主席树入门模板

看了很久的主席树,最后看https://blog.csdn.net/williamsun0122/article/details/77871278这篇终于看懂了 #include <stdio.h> #include<algorithm> using namespace std; typedef long long ll; const int maxn = 1e5+5; int T[maxn],L[maxn*20],R[maxn*20],sum[maxn*20]; //sz[]为原

zoj2112 主席树动态第k大 (主席树&amp;&amp;树状数组)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

hdoj 2665 Kth number主席树裸

Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9417    Accepted Submission(s): 2938 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The fi

4504: K个串 主席树+优先队列

这道题因为有一个数在序列中出现多次只算一次的限制.我们可以这样搞.假设在当前题意下求给定右端点的区间最值.那么我们可以预处理出每个数前一次出现的位置pre[i] .接下来从左到右加入每一个值,就是在 pre[i] + 1 —— i 这个区间内加上 v[i] 的值,这样就可以得到以当前 i 点为右端点的各个区间的值(很明显维护一下最值就好了).接下来很明显有n个版本的线段树(如果你说一开始那个空的线段树也算一个版本的话,就有n+1个),那就要用主席树动态开点.而取第K大值的操作有点像超级钢琴,不过

【POJ 2104】 K-th Number 主席树模板题

达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没有评测,但我立下flag这个代码一定能A.我的同学在自习课上考语文,然而机房党都跑到机房来避难了\(^o^)/~ #include<cstdio> #include<cstring> #include<algorithm> #define for1(i,a,n) for(i