[POJ 2104]K-th Number【模板】(主席树)
题目背景
这是个非常经典的主席树入门题——静态区间第K小
数据已经过加强,请使用主席树。同时请注意常数优化
题目描述
如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。
输入输出格式
输入格式:第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。
第二行包含N个正整数,表示这个序列各项的数字。
接下来M行每行包含三个整数l,r,k l, r, kl,r,k , 表示查询区间[l,r][l, r][l,r]内的第k小值。
输出格式:输出包含k行,每行1个正整数,依次表示每一次查询的结果
输入输出样例
输入样例#1:
5 5 25957 6405 15770 26287 26465 2 2 1 3 4 1 4 5 1 1 2 2 4 4 1
输出样例#1:
6405 15770 26287 25957 26287
说明
数据范围:
对于20%的数据满足:1≤N,M≤10
对于50%的数据满足:1≤N,M≤1033
对于80%的数据满足:1≤N,M≤1055
对于100%的数据满足:1≤N,M≤2⋅1055
对于数列中的所有数aii,均满足−109≤ai≤109-{10}^9 \leq a_i \leq {10}^9−109≤ai≤109
样例数据说明:
N=5,数列长度为5,数列从第一项开始依次为25957,6405,15770,26287,26465
第一次查询为[2,2]区间内的第一小值,即为6405
第二次查询为[3,4]区间内的第一小值,即为15770
第三次查询为[4,5]区间内的第一小值,即为26287
第四次查询为[1,2]]区间内的第二小值,即为25957
第五次查询为[4,4]区间内的第一小值,即为26287
主席树真奇妙
给出两位巨佬的链接
第一个很详细的解释了主席树
第二个给出了此题的所有做法
http://www.cnblogs.com/zyf0163/p/4749042.html
http://www.cnblogs.com/NaVi-Awson/p/7325571.html
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=200000; 7 struct Node 8 { 9 int key; 10 Node *ch[2]; 11 }S[N*20],*pos=S; 12 Node *root[N+5]; 13 int a[N+5],b[N+5],n,m,sz,rem[N+5]; 14 void build(Node* &rt,int l,int r) 15 { 16 rt=++pos; 17 rt->key=0; 18 if (l==r) return; 19 int mid=(l+r)/2; 20 build(rt->ch[0],l,mid); 21 build(rt->ch[1],mid+1,r); 22 } 23 void insert(Node* &rt,int l,int r,int k) 24 { 25 Node *x=rt; 26 rt=++pos; 27 rt->ch[0]=x->ch[0]; 28 rt->ch[1]=x->ch[1]; 29 rt->key=x->key+1; 30 if (l==r) return; 31 int mid=(l+r)/2; 32 if (k<=mid) insert(rt->ch[0],l,mid,k); 33 else insert(rt->ch[1],mid+1,r,k); 34 } 35 int query(Node* rl,Node* rr,int l,int r,int k) 36 { 37 if (l==r) return l; 38 int mid=(l+r)/2; 39 int x=rr->ch[0]->key-rl->ch[0]->key; 40 if (x>=k) return query(rl->ch[0],rr->ch[0],l,mid,k); 41 else return query(rl->ch[1],rr->ch[1],mid+1,r,k-x); 42 } 43 int main() 44 {int i,j,x,y,k; 45 cin>>n>>m; 46 for (i=1;i<=n;i++) 47 { 48 scanf("%d",&a[i]); 49 b[i]=a[i]; 50 } 51 sort(b+1,b+n+1); 52 sz=unique(b+1,b+n+1)-(b+1); 53 for (i=1;i<=n;i++) 54 a[i]=lower_bound(b+1,b+sz+1,a[i])-b; 55 build(root[0],1,n); 56 for (i=1;i<=n;i++) 57 { 58 root[i]=root[i-1]; 59 insert(root[i],1,n,a[i]); 60 } 61 while (m--) 62 { 63 scanf("%d%d%d",&x,&y,&k); 64 int ans=query(root[x-1],root[y],1,n,k); 65 printf("%d\n",b[ans]); 66 } 67 }