题目链接:http://poj.org/problem?id=2104
题目思路:划分树求区间第k小数。
说明:划分树实现有问题,这个程序只适合每个元素不相同的情况,poj的数据弱了,做了下一题才发现有问题。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<string> #include<queue> #include<algorithm> #include<vector> #include<stack> #include<list> #include<iostream> #include<map> using namespace std; #define inf 0x3f3f3f3f #define M 110000 int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } int tr[20][M],s[20][M]; int sorted[M]; void build(int d,int l,int r) { if(l==r) return ; int i,j,k,mid; mid=(l+r)>>1,j=l,k=mid+1; for(i=l;i<=r;i++) { s[d][i]=s[d][i-1]; if(tr[d][i]<=sorted[mid]) { s[d][i]++; tr[d+1][j++]=tr[d][i]; } else { tr[d+1][k++]=tr[d][i]; } } build(d+1,l,mid); build(d+1,mid+1,r); } int getkth(int d,int lp,int rp,int l,int r,int k) { int lt,rt; if(lp==rp) return tr[d][lp]; int mid=(lp+rp)>>1; if(k<=s[d][r]-s[d][l-1]) { lt=lp+s[d][l-1]-s[d][lp-1]; rt=lp+s[d][r]-s[d][lp-1]-1; return getkth(d+1,lp,mid,lt,rt,k); } else { lt=mid+1+(l-lp)-(s[d][l-1]-s[d][lp-1]); rt=mid+(r-lp+1)-(s[d][r]-s[d][lp-1]); return getkth(d+1,mid+1,rp,lt,rt,k-(s[d][r]-s[d][l-1])); } } int main() { int i,n,m,l,r,k; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) { scanf("%d",&tr[0][i]); sorted[i]=tr[0][i]; } sort(sorted+1,sorted+n+1); for(i=0;i<20;i++) s[i][0]=0; build(0,1,n); // for(i=1;i<=n;i++) // { // printf("i %d s %d\n",i,s[0][i]); // } while(m--) { scanf("%d%d%d",&l,&r,&k); printf("%d\n",getkth(0,1,n,l,r,k)); } } }