[POJ2104] K-th Number(归并树,二分)
题目链接:http://poj.org/problem?id=2104
题意:略
最近想学一下分块,搜到了这道题。结果在《挑战》上另外看到了另外的用线段树做的算法。后来才知道,这种记录归并排序过程的树叫归并树。利用STL,非常好实现。
思路就是首先二分答案,拿着这个答案在归并树上找对应区间比这个数小的数的个数ret,找到==k的为止。
稍微对拍后,重新划了一下query的区间才发现是第40行写搓了。最近不刷题,码力下降了啊。。
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <cassert> 8 #include <cstdio> 9 #include <bitset> 10 #include <vector> 11 #include <deque> 12 #include <queue> 13 #include <stack> 14 #include <ctime> 15 #include <set> 16 #include <map> 17 #include <cmath> 18 using namespace std; 19 20 #define lrt rt << 1 21 #define rrt rt << 1 | 1 22 const int maxn = 100100; 23 int n, q, a[maxn]; 24 vector<int> seg[maxn<<2]; 25 26 void build(int l, int r, int rt) { 27 if(l == r) { 28 seg[rt].clear(); 29 seg[rt].push_back(a[l]); 30 return; 31 } 32 int mid = (l + r) >> 1; 33 build(l, mid, lrt); 34 build(mid+1, r, rrt); 35 seg[rt].resize(r-l+1); 36 merge(seg[lrt].begin(), seg[lrt].end(), seg[rrt].begin(), seg[rrt].end(), seg[rt].begin()); 37 } 38 39 int query(int L, int R, int v, int l, int r, int rt) { 40 if(R < l || r < L) return 0; 41 if(L <= l && r <= R) return upper_bound(seg[rt].begin(), seg[rt].end(), v) - seg[rt].begin(); 42 int mid = (l + r) >> 1; 43 return query(L, R, v, l, mid, lrt) + query(L, R, v, mid+1, r, rrt); 44 } 45 46 inline bool scan_d(int &num) { 47 char in;bool IsN=false; 48 in=getchar(); 49 if(in==EOF) return false; 50 while(in!='-'&&(in<'0'||in>'9')) in=getchar(); 51 if(in=='-'){ IsN=true;num=0;} 52 else num=in-'0'; 53 while(in=getchar(),in>='0'&&in<='9'){ 54 num*=10,num+=in-'0'; 55 } 56 if(IsN) num=-num; 57 return true; 58 } 59 60 inline void out(int x) { 61 if (x > 9) out(x / 10); 62 putchar(x % 10 + '0'); 63 } 64 65 int main() { 66 // freopen("in", "r", stdin); 67 // freopen("out", "w", stdout); 68 int T, l, r, k; 69 while(scan_d(n)) { 70 scan_d(q); 71 for(int i = 1; i <= n; i++) scan_d(a[i]); 72 build(1, n, 1); 73 sort(a+1, a+n+1); 74 while(q--) { 75 scan_d(l); scan_d(r); scan_d(k); 76 int lo = 1, hi = n; 77 int v; 78 while(lo <= hi) { 79 int mid = (lo + hi) >> 1; 80 int ret = query(l, r, a[mid], 1, n, 1); 81 if(ret >= k) { 82 hi = mid - 1; 83 v = a[mid]; 84 } 85 else lo = mid + 1; 86 } 87 printf("%d\n", v); 88 } 89 } 90 return 0; 91 }