POJ 2104
划分树。
具体划分树算法可以参考下面总结:
但上面的算法代码有点错误,可以看我的代码下面指出
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=100050; int sorted[N]; struct node{ int val[N]; int num[N]; }tp[30]; int n,m; void build(int lft,int rht,int p){ if(lft==rht) return ; int i,mid=(lft+rht)/2; int isame=mid-lft+1,same=0; for(i=lft;i<=rht;i++){ if(tp[p].val[i]<sorted[mid]) isame--; } int ln=lft,rn=mid+1; for(i = lft; i <= rht; i++) { if(i == lft) { tp[p].num[i] = 0; } else { tp[p].num[i] = tp[p].num[i-1]; } if(tp[p].val[i] < sorted[mid]) { tp[p].num[i]++; tp[p+1].val[ln++] = tp[p].val[i]; }else if(tp[p].val[i] > sorted[mid]) { tp[p+1].val[rn++] = tp[p].val[i]; }else { if(same < isame) { same++; tp[p].num[i]++; tp[p+1].val[ln++] = tp[p].val[i]; }else { tp[p+1].val[rn++] = tp[p].val[i]; } } } build(lft, mid, p+1); build(mid+1, rht, p+1); } int query(int a, int b, int k, int p, int lft, int rht) { if(lft == rht) return tp[p].val[a]; int s, ss, b2, bb, mid = (lft+rht)/2; if(a == lft) { s = tp[p].num[b]; ss = 0; } else { s = tp[p].num[b] - tp[p].num[a-1]; ss = tp[p].num[a-1]; } if(s >= k) { a = lft + ss; b = lft + ss + s - 1; return query(a, b, k, p+1, lft, mid); } else { bb = a - lft - ss; b2 = b - a + 1 - s; //这里应该是加1 a = mid + bb + 1; b = mid + bb + b2; return query(a, b, k-s,p+1, mid+1, rht); } } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=n;i++){ scanf("%d",&tp[0].val[i]); sorted[i]=tp[0].val[i]; } sort(sorted+1,sorted+1+n); build(1,n,0); int l,r,k; for(int i=1;i<=m;i++){ scanf("%d%d%d",&l,&r,&k); printf("%d\n",query(l,r,k,0,1,n)); } } return 0; }