因为这道题没有删除修改之类的,所以很多人会用离散化之后的线段树来做,但是实际上(可能是我懒得去做离散化这个操作了),然后就是直接写可持久化线段树,区间的长度就是int的从最小到最大的长度,然后记录的是size,我们最后直接返回的是对应的位置即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <string> 5 #include <cstring> 6 #include <algorithm> 7 #include <limits> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <set> 12 #include <map> 13 #define lowbit(x) ( x&(-x) ) 14 #define pi 3.141592653589793 15 #define e 2.718281828459045 16 #define INF 0x3f3f3f3f 17 #define HalF (l + r)>>1 18 #define lsn rt<<1 19 #define rsn rt<<1|1 20 #define Lson lsn, l, mid 21 #define Rson rsn, mid+1, r 22 #define QL Lson, ql, qr 23 #define QR Rson, ql, qr 24 #define myself rt, l, r 25 using namespace std; 26 typedef unsigned long long ull; 27 typedef long long ll; 28 const int maxN = 1e5 + 7, _UP = 2147483647, _DOWN = -2147483648; 29 int N, M, root[maxN], tot, siz[40 * maxN], lc[40 * maxN], rc[40 * maxN]; 30 inline void insert(int &rt, int old, ll l, ll r, int qx) 31 { 32 rt = ++tot; 33 siz[rt] = siz[old] + 1; lc[rt] = lc[old]; rc[rt] = rc[old]; 34 if(l == r) return; 35 ll mid = HalF; 36 if(qx <= mid) insert(lc[rt], lc[old], l, mid, qx); 37 else insert(rc[rt], rc[old], mid + 1, r, qx); 38 } 39 inline ll query(int now, int old, ll l, ll r, int k) 40 { 41 if(l == r) return l; 42 ll mid = HalF; 43 if(k <= siz[lc[now]] - siz[lc[old]]) return query(lc[now], lc[old], l, mid, k); 44 else return query(rc[now], rc[old], mid + 1, r, k - siz[lc[now]] + siz[lc[old]]); 45 } 46 inline void init() 47 { 48 for(int i=0; i<=tot; i++) root[i] = 0; 49 tot = 0; 50 } 51 int main() 52 { 53 while(scanf("%d%d", &N, &M) != EOF) 54 { 55 init(); 56 for(int i=1, val; i<=N; i++) 57 { 58 scanf("%d", &val); 59 insert(root[i], root[i - 1], _DOWN, _UP, val); 60 } 61 int l, r, k; 62 while(M--) 63 { 64 scanf("%d%d%d", &l, &r, &k); 65 printf("%lld\n", query(root[r], root[l-1], _DOWN, _UP, k)); 66 } 67 } 68 return 0; 69 }