查询区间第K大,而且没有修改。
使用划分树是可以做的。
作为主席树的入门题,感觉太神奇了,Orz
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-9-4 20:13:20 4 File Name :POJ2104.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 21 const int MAXN = 100010; 22 const int M = MAXN * 30; 23 int n,q,m,tot; 24 int a[MAXN], t[MAXN]; 25 int T[M], lson[M], rson[M], c[M]; 26 27 void Init_hash() 28 { 29 for(int i = 1; i <= n;i++) 30 t[i] = a[i]; 31 sort(t+1,t+1+n); 32 m = unique(t+1,t+1+n)-t-1; 33 } 34 int build(int l,int r) 35 { 36 int root = tot++; 37 c[root] = 0; 38 if(l != r) 39 { 40 int mid = (l+r)>>1; 41 lson[root] = build(l,mid); 42 rson[root] = build(mid+1,r); 43 } 44 return root; 45 } 46 int hash(int x) 47 { 48 return lower_bound(t+1,t+1+m,x) - t; 49 } 50 int update(int root,int pos,int val) 51 { 52 int newroot = tot++, tmp = newroot; 53 c[newroot] = c[root] + val; 54 int l = 1, r = m; 55 while(l < r) 56 { 57 int mid = (l+r)>>1; 58 if(pos <= mid) 59 { 60 lson[newroot] = tot++; rson[newroot] = rson[root]; 61 newroot = lson[newroot]; root = lson[root]; 62 r = mid; 63 } 64 else 65 { 66 rson[newroot] = tot++; lson[newroot] = lson[root]; 67 newroot = rson[newroot]; root = rson[root]; 68 l = mid+1; 69 } 70 c[newroot] = c[root] + val; 71 } 72 return tmp; 73 } 74 int query(int left_root,int right_root,int k) 75 { 76 int l = 1, r = m; 77 while( l < r) 78 { 79 int mid = (l+r)>>1; 80 if(c[lson[left_root]]-c[lson[right_root]] >= k ) 81 { 82 r = mid; 83 left_root = lson[left_root]; 84 right_root = lson[right_root]; 85 } 86 else 87 { 88 l = mid + 1; 89 k -= c[lson[left_root]] - c[lson[right_root]]; 90 left_root = rson[left_root]; 91 right_root = rson[right_root]; 92 } 93 } 94 return l; 95 } 96 int main() 97 { 98 //freopen("in.txt","r",stdin); 99 //freopen("out.txt","w",stdout); 100 while(scanf("%d%d",&n,&q) == 2) 101 { 102 tot = 0; 103 for(int i = 1;i <= n;i++) 104 scanf("%d",&a[i]); 105 Init_hash(); 106 T[n+1] = build(1,m); 107 for(int i = n;i ;i--) 108 { 109 int pos = hash(a[i]); 110 T[i] = update(T[i+1],pos,1); 111 } 112 while(q--) 113 { 114 int l,r,k; 115 scanf("%d%d%d",&l,&r,&k); 116 printf("%d\n",t[query(T[l],T[r+1],k)]); 117 } 118 } 119 return 0; 120 }