http://acm.hdu.edu.cn/showproblem.php?pid=4251
n个数,求给定区间中间大小的元素的值
Sample Input
5
5 3 2 4 1
3
1 3
2 4
3 5
5
10 6 4 8 2
3
1 3
2 4
3 5
Sample Output
Case 1:
3
3
2
Case 2:
6
6
4
1 #include<cstdio> 2 #include< string > 3 #include<vector> 4 #include<algorithm> 5 #define N 100009 6 using namespace std; 7 int n; 8 int arr[N]; // 原数据 9 int od[N]; // 排序后 10 int lfnum[ 20 ][N]; // 元素所在区间的当前位置进入左孩子的元素的个数 11 int val[ 20 ][N]; // 记录第k层当前位置的元素的值 12 bool cmp( const int &x, const int &y){ return arr[x]< arr[y];} 13 void build( int l, int r, int d) 14 { 15 if (l==r) return ; 16 int mid=(l+r)>> 1 ,p= 0 ; 17 for ( int i=l;i<=r;i++ ) 18 { 19 if (val[d][i]<= mid) 20 { 21 val[d+ 1 ][l+p]= val[d][i]; 22 lfnum[d][i]=++ p; 23 } 24 else 25 { 26 lfnum[d][i]= p; 27 val[d+ 1 ][mid+i+ 1 -l-p]= val[d][i]; 28 } 29 } 30 build(l,mid,d+ 1 ); 31 build(mid+ 1 ,r,d+ 1 ); 32 } 33 // 求区间[s,e]第k大的元素 34 int query( int s, int e, int k, int l= 1 , int r=n, int d= 0 ) 35 { 36 if (l==r) return l; 37 int mid=(l+r)>> 1 ,ss,ee; 38 ss=(s==l? 0 :lfnum[d][s- 1 ]); 39 ee= lfnum[d][e]; 40 if (ee-ss>=k) return query(l+ss,l+ee- 1 ,k,l,mid,d+ 1 ); 41 return query(mid+ 1 +(s-l-ss),mid+ 1 +(e-l-ee),k-(ee-ss),mid+ 1 ,r,d+ 1 ); 42 } 43 int main() 44 { 45 int cas= 0 ,m,l,r; 46 while (scanf( " %d " ,&n)!= EOF) 47 { 48 printf( " Case %d:\n " ,++ cas); 49 for ( int i= 1 ;i<=n;i++) scanf( " %d " ,arr+i),od[i]= i; 50 sort(od+ 1 ,od+n+ 1 ,cmp); 51 for ( int i= 1 ;i<=n;i++) val[ 0 ][od[i]]= i; 52 build( 1 ,n, 0 ); 53 scanf( " %d " ,& m); 54 while (m-- ) 55 { 56 int num,k; 57 scanf( " %d%d " ,&l,& r); 58 k=(r-l)/ 2 + 1 ; // 中间大小 59 num= query(l,r,k); 60 int ans= arr[od[num]]; 61 printf( " %d\n " ,ans); 62 } 63 } 64 }