题目链接:http://poj.org/problem?id=2104
题意:给一个数列,求给定区间第k小的数是多少。
思路:可以按照数字出现的次数为值建立线段树,每插入一个数字就维护一棵线段树,这样求某个区间(比如求[x,y]区间内)的第k小时就可以二分了。当tree[tree[x].l].sum - tree[tree[y].l].sum >= k时去查左儿子,tree[tree[x].l].sum - tree[tree[y].l].sum < k时去查右儿子。数据大,所以要离散化后再做。
1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm> 18 #include <iostream> 19 #include <iomanip> 20 #include <cstring> 21 #include <climits> 22 #include <complex> 23 #include <fstream> 24 #include <cassert> 25 #include <cstdio> 26 #include <bitset> 27 #include <vector> 28 #include <deque> 29 #include <queue> 30 #include <stack> 31 #include <ctime> 32 #include <set> 33 #include <map> 34 #include <cmath> 35 using namespace std; 36 #define fr first 37 #define sc second 38 #define cl clear 39 #define BUG puts("here!!!") 40 #define W(a) while(a--) 41 #define pb(a) push_back(a) 42 #define Rint(a) scanf("%d", &a) 43 #define Rll(a) scanf("%I64d", &a) 44 #define Rs(a) scanf("%s", a) 45 #define Cin(a) cin >> a 46 #define FRead() freopen("in", "r", stdin) 47 #define FWrite() freopen("out", "w", stdout) 48 #define Rep(i, len) for(int i = 0; i < (len); i++) 49 #define For(i, a, len) for(int i = (a); i < (len); i++) 50 #define Cls(a) memset((a), 0, sizeof(a)) 51 #define Clr(a, x) memset((a), (x), sizeof(a)) 52 #define Full(a) memset((a), 0x7f7f7f, sizeof(a)) 53 #define lrt rt << 1 54 #define rrt rt << 1 | 1 55 #define pi 3.14159265359 56 #define RT return 57 #define lowbit(x) x & (-x) 58 #define onecnt(x) __builtin_popcount(x) 59 typedef long long LL; 60 typedef long double LD; 61 typedef unsigned long long ULL; 62 typedef pair<int, int> pii; 63 typedef pair<string, int> psi; 64 typedef pair<LL, LL> pll; 65 typedef map<string, int> msi; 66 typedef vector<int> vi; 67 typedef vector<LL> vl; 68 typedef vector<vl> vvl; 69 typedef vector<bool> vb; 70 71 const int maxn = 1000010; 72 int n, m; 73 int cnt, root[maxn], a[maxn], x, y, k; 74 typedef struct Node { 75 int l, r, sum; 76 }Node; 77 int h[maxn], hcnt; 78 Node tree[maxn*40]; 79 80 int getid(int x) { 81 return lower_bound(h+1, h+hcnt+1, x) - h; 82 } 83 84 int build(int l, int r) { 85 int rt = cnt++; 86 tree[rt].sum = 0; 87 if(l != r) { 88 int mid = (l + r) >> 1; 89 tree[rt].l = build(l, mid); 90 tree[rt].r = build(mid+1, r); 91 } 92 return rt; 93 } 94 95 int update(int rt, int pos, int val) { 96 int k = cnt++, tmp = k; 97 tree[k].sum = tree[rt].sum + val; 98 int l = 1, r = hcnt; 99 while(l < r) { 100 int mid = (l + r) >> 1; 101 if(pos <= mid) { 102 tree[k].l = cnt++; tree[k].r = tree[rt].r; 103 k = tree[k].l; rt = tree[rt].l; 104 r = mid; 105 } 106 else { 107 tree[k].r = cnt++; tree[k].l = tree[rt].l; 108 k = tree[k].r; rt = tree[rt].r; 109 l = mid + 1; 110 } 111 tree[k].sum = tree[rt].sum + val; 112 } 113 return tmp; 114 } 115 116 int query(int x, int y, int k) { 117 int l = 1, r = hcnt; 118 while(l < r) { 119 int mid = (l + r) >> 1; 120 if(tree[tree[x].l].sum - tree[tree[y].l].sum >= k) { 121 r = mid; 122 x = tree[x].l; 123 y = tree[y].l; 124 } 125 else { 126 l = mid + 1; 127 k -= tree[tree[x].l].sum - tree[tree[y].l].sum; 128 x = tree[x].r; 129 y = tree[y].r; 130 } 131 } 132 return l; 133 } 134 135 int main() { 136 // FRead(); 137 cnt = 0; 138 Rint(n); Rint(m); 139 For(i, 1, n+1) { 140 Rint(a[i]); 141 h[i] = a[i]; 142 } 143 sort(h+1, h+n+1); 144 hcnt = unique(h+1, h+n+1) - h - 1; 145 root[n+1] = build(1, hcnt); 146 for(int i = n; i >= 1; i--) { 147 root[i] = update(root[i+1], getid(a[i]), 1); 148 } 149 W(m) { 150 Rint(x), Rint(y), Rint(k); 151 printf("%d\n", h[query(root[x], root[y+1], k)]); 152 } 153 return 0; 154 }
时间: 2024-10-15 09:59:12