数据结构——划分树模板
http://www.notonlysuccess.com/index.php/divide-tree/
http://blog.sina.com.cn/s/blog_5f5353cc0100ki2e.html
以上为两个不错的讲解:
struct node{ int l,r; int mid(){ return (l + r)>>1; } }tt[N<<2]; int toLeft[20][N]; int val[20][N],sorted[N]; int n,q; void build(int l,int r,int rt,int d){ int i; tt[rt].l = l; tt[rt].r = r; if (l == r) return ; int m = tt[rt].mid(); int lsame = m - l + 1;//先假设做区间与m相等的放满 //一一排除,保证左区间放的是<=sorted[m]的值 for (i = l; i <= r; ++i){ if (val[d][i] < sorted[m]) lsame--; } int lpos = l; int rpos = m + 1; int same = 0; for (i = l; i <= r; ++i){ if (i == l) toLeft[d][i] = 0; else toLeft[d][i] = toLeft[d][i - 1]; if (val[d][i] < sorted[m]){ toLeft[d][i]++; val[d + 1][lpos++] = val[d][i]; } else if (val[d][i] > sorted[m]){ val[d + 1][rpos++] = val[d][i]; } else{ if (same < lsame){ toLeft[d][i]++; val[d + 1][lpos++] = val[d][i]; same++; } else{ val[d + 1][rpos++] = val[d][i]; } } } build(lc,d + 1); build(rc,d + 1); } int query(int L,int R,int k,int d,int rt){ // printf("%d %d\n",L,R); if (L == R){ return val[d][L]; } int s = 0; int ss = 0; if (L == tt[rt].l){ ss = 0; s = toLeft[d][R]; } else{ ss = toLeft[d][L - 1]; s = toLeft[d][R] - toLeft[d][L - 1]; } if (k <= s){ int newl = tt[rt].l + ss; int newr = newl + s - 1; return query(newl,newr,k,d + 1,rt<<1); } else{ int m = tt[rt].mid(); int bb = L - tt[rt].l - ss; int b = R - L + 1 - s; int newl = m + bb + 1; int newr = newl + b - 1; return query(newl,newr,k - s,d + 1,rt<<1|1); } }