参考HH大神的模版。对其中一些转移,还没想清楚,大体明白上是怎么回事了,划分树就是类似快排,但有点点区别的。多做几个题,慢慢理解。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 #define N 100100 8 struct node 9 { 10 int l,r; 11 }tree[4*N]; 12 int sorted[N]; 13 int lnum[20][N]; 14 int val[20][N]; 15 16 void build(int d,int l,int r,int rt) 17 { 18 int m,lsame,i,lpos,rpos,same; 19 tree[rt].l = l; 20 tree[rt].r = r; 21 if(l == r) return ; 22 m = (l+r)>>1; 23 lsame = (m - l + 1); 24 for(i = l;i <= r;i ++) 25 { 26 if(val[d][i] < sorted[m]) 27 lsame --; 28 } 29 lpos = l; 30 rpos = m+1; 31 same = 0; 32 for(i = l;i <= r;i ++) 33 { 34 if(i == l)//lnum[d][i]表示[tree[rt].l, i ]区域里有多少个数分到左边 35 lnum[d][i] = 0; 36 else 37 lnum[d][i] = lnum[d][i-1]; 38 if(val[d][i] < sorted[m]) 39 { 40 lnum[d][i] ++; 41 val[d+1][lpos++] = val[d][i]; 42 } 43 else if(val[d][i] > sorted[m]) 44 { 45 val[d+1][rpos++] = val[d][i]; 46 } 47 else 48 { 49 if(same < lsame) 50 { 51 same ++; 52 lnum[d][i] ++; 53 val[d+1][lpos++] = val[d][i]; 54 } 55 else 56 { 57 val[d+1][rpos++] = val[d][i]; 58 } 59 } 60 } 61 build(d+1,lson); 62 build(d+1,rson); 63 } 64 int query(int d,int k,int l,int r,int rt) 65 { 66 int s,ss,nl,nr,m,rs,rss;//s表示[ l , r ]有多少个分到左边 67 if(l == r)//ss表示 [tree[idx].left , l-1 ]有多少个分到左边 68 { 69 return val[d][l]; 70 } 71 if(l == tree[rt].l) 72 { 73 s = lnum[d][r]; 74 ss = 0; 75 } 76 else 77 { 78 s = lnum[d][r] - lnum[d][l-1]; 79 ss = lnum[d][l-1]; 80 } 81 if(s >= k) 82 { 83 nl = ss + tree[rt].l; 84 nr = ss + tree[rt].l + s - 1; 85 return query(d+1,k,nl,nr,rt<<1); 86 } 87 else 88 { 89 m = (tree[rt].l + tree[rt].r)>>1; 90 rss = l - tree[rt].l - ss; 91 rs = r - l + 1 - s; 92 nl = m + rss + 1; 93 nr = m + rs + rss; 94 return query(d+1,k-s,nl,nr,rt<<1|1); 95 } 96 } 97 int main() 98 { 99 int i,n,m,x,y,k; 100 while(scanf("%d%d",&n,&m)!=EOF) 101 { 102 for(i = 1;i <= n;i ++) 103 { 104 scanf("%d",&val[0][i]); 105 sorted[i] = val[0][i]; 106 } 107 sort(sorted+1,sorted+n+1); 108 build(0,1,n,1); 109 for(i = 0;i < m;i ++) 110 { 111 scanf("%d%d%d",&x,&y,&k); 112 printf("%d ",query(0,k,x,y,1)); 113 } 114 } 115 return 0; 116 }