题意:给一串数列,然后求其中的各个范围内的第k大数
分析:划分树,具体分析见划分树算法。跟之前做过2104相比,这道题好象没有重复的元素。
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 //14256K 1813MS 7 //划分树 8 const int maxnum=100001; 9 struct tree 10 { 11 int array[maxnum]; 12 int sum[maxnum]; 13 }tree[20]; 14 int sorted[maxnum]; 15 16 void build_tree(int cur,int l,int r) 17 { 18 if(l==r) 19 return ; 20 int i; 21 int m=(l+r)>>1; 22 int lsame=m-l+1;//? 23 for(i=l;i<=r;i++) 24 if(tree[cur].array[i]<sorted[m]) 25 lsame--; 26 27 int lnum=l,rnum=m+1; 28 for(i=l;i<=r;i++) 29 { 30 if(i==l) 31 tree[cur].sum[i]=0; 32 else 33 tree[cur].sum[i]=tree[cur].sum[i-1]; 34 if(tree[cur].array[i]<sorted[m]) 35 { 36 tree[cur].sum[i]++; 37 tree[cur+1].array[lnum++]=tree[cur].array[i]; 38 } 39 else if(tree[cur].array[i]>sorted[m]) 40 tree[cur+1].array[rnum++]=tree[cur].array[i]; 41 else 42 { 43 if(lsame>0) 44 { 45 lsame--; 46 tree[cur].sum[i]++; //? 47 tree[cur+1].array[lnum++]=tree[cur].array[i]; 48 } 49 else 50 tree[cur+1].array[rnum++]=tree[cur].array[i]; 51 } 52 } 53 build_tree(cur+1,l,m); 54 build_tree(cur+1,m+1,r); 55 } 56 57 int find(int cur,int st,int ed,int l,int r,int k) 58 { 59 if(l==r) 60 return tree[cur].array[l]; 61 int lnum,rnum; 62 int m=(st+ed)>>1; 63 if(l-1<st) 64 lnum=0; 65 else 66 lnum=tree[cur].sum[l-1]; 67 rnum=tree[cur].sum[r]; 68 if(rnum-lnum>=k) 69 return find(cur+1,st,m,st+lnum,st+rnum-1,k); 70 else 71 return find(cur+1,m+1,ed,m+1+l-st-lnum,m+1+r-st-rnum,k-(rnum-lnum)); 72 } 73 74 int main() 75 { 76 int n,m,i; 77 scanf("%d%d",&n,&m); 78 for(i=1;i<=n;i++) 79 { 80 scanf("%d",&tree[0].array[i]); 81 sorted[i]=tree[0].array[i]; 82 } 83 sort(sorted+1,sorted+1+n); 84 build_tree(0,1,n); 85 86 int p,r,k; 87 while(m--) 88 { 89 scanf("%d%d%d",&p,&r,&k); 90 printf("%d\n",find(0,1,n,p,r,k)); 91 } 92 return 0; 93 } 94 95 /* 96 7 2 97 1 5 2 6 3 7 4 98 1 5 3 99 2 7 1 100 */