在算法篇介绍过求这样的某一个范围内第k大的数的三种方法。
分治方法,对于求一组范围内的值可以考虑。但是求多组的时候就不行了,因为这种方法会改变原数组的排序。如果要有多组询问时,就必须赋值到另外一个数组中,结果TLE.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <memory.h> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxnum=100005; 8 int array[maxnum]; 9 int a[maxnum]; 10 11 int patition(int p,int r) 12 { 13 int temp=a[r]; 14 int i=p-1; 15 int j,t; 16 for(j=p;j<=r-1;j++) 17 { 18 if(a[j]<=temp) 19 { 20 i++; 21 t=a[i]; 22 a[i]=a[j]; 23 a[j]=t; 24 } 25 } 26 t=a[i+1]; 27 a[i+1]=a[r]; 28 a[r]=t; 29 return i+1; 30 } 31 32 int select(int p,int r,int i) 33 { 34 if(p==r) 35 return a[p]; 36 int q=patition(p,r); 37 int k=q-p+1; 38 if(k==i) 39 return a[q]; 40 else if(i<k) 41 return select(p,q-1,i); 42 else 43 return select(q+1,r,i-k); 44 } 45 46 void function(int p,int r,int i) 47 { 48 int k; 49 int cnt=0; 50 for(k=p;k<=r;k++) 51 a[cnt++]=array[k]; 52 // for(k=0;k<cnt;k++) 53 // cout<<a[k]<<" "; 54 // cout<<endl; 55 printf("%d\n",select(0,cnt-1,i)); 56 } 57 58 int main() 59 { 60 int n,m; 61 scanf("%d%d",&n,&m); 62 int i,p,q,j; 63 for(i=0;i<n;i++) 64 scanf("%d",&array[i]); 65 while(m--) 66 { 67 scanf("%d%d%d",&p,&q,&j); 68 function(p-1,q-1,j); 69 } 70 return 0; 71 } 72 73 74 /* 75 6 1 76 1 1 1 1 1 1 77 3 5 2 78 */
划分树方法可以用于求多组的情况,且查询时间复杂度O(lgn)
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <memory.h> 5 using namespace std; 6 const int maxnum=100005; 7 struct node 8 { 9 int array[maxnum]; 10 int sum[maxnum]; 11 }tree[20]; //树有10层 12 int sorted[maxnum]; 13 14 void Build_tree(int cur,int l,int r) 15 { 16 if(l==r) 17 return ; 18 int m=(l+r)/2; 19 int i; 20 21 int lsame=m-l+1; //这是往cur+1左子树中一共放入的节点,其中小于中值的一定在左子树中,等于中值的可能在左子树,也可能在右子树 22 for(i=l;i<=r;i++) 23 if(tree[cur].array[i]<sorted[m]) 24 lsame--;//与中值相同的放在左子树中的个数 25 26 int lnum=l,rnum=m+1; 27 for(i=l;i<=r;i++) 28 { 29 if(i==l) 30 tree[cur].sum[i]=0; 31 else 32 tree[cur].sum[i]=tree[cur].sum[i-1]; 33 if(tree[cur].array[i]<sorted[m]) 34 { 35 tree[cur].sum[i]++; 36 tree[cur+1].array[lnum++]=tree[cur].array[i]; 37 } 38 else if(tree[cur].array[i]>sorted[m]) 39 tree[cur+1].array[rnum++]=tree[cur].array[i]; 40 else //if(tree[cur].array[i]==sorted[m]) 41 { 42 if(lsame>0) 43 { 44 lsame--; 45 tree[cur].sum[i]++; 46 tree[cur+1].array[lnum++]=tree[cur].array[i]; 47 } 48 else 49 tree[cur+1].array[rnum++]=tree[cur].array[i]; 50 } 51 } 52 Build_tree(cur+1,l,m); 53 Build_tree(cur+1,m+1,r); 54 } 55 56 int find(int cur,int st,int ed,int l,int r,int k) 57 { 58 //cout<<cur<<" "<<st<<" "<<ed<<" "<<l<<" "<<r<<" "<<k<<endl; 59 if(l==r) 60 return tree[cur].array[l]; 61 int m=(st+ed)/2; 62 int lnum,rnum; 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 75 int main() 76 { 77 int n,m; 78 scanf("%d%d",&n,&m); 79 int i; 80 for(i=1;i<=n;i++) 81 { 82 scanf("%d",&tree[0].array[i]); 83 sorted[i]=tree[0].array[i]; 84 } 85 sort(sorted+1,sorted+n+1); 86 Build_tree(0,1,n); 87 88 int p,r,k; 89 int res; 90 while(m--) 91 { 92 scanf("%d%d%d",&p,&r,&k); 93 res=find(0,1,n,p,r,k); 94 printf("%d\n",res); 95 } 96 97 return 0; 98 } 99 100 101 /* 102 6 1 103 1 1 1 1 1 1 104 2 4 2 105 10 7 2 5 1 4 6 106 */ 107 108 109 // for(i=0;i<4;i++) 110 // { 111 // cout<<i<<endl; 112 // for(j=1;j<maxnum;j++) 113 // cout<<tree[i].array[j]<<" "; 114 // cout<<endl; 115 // for(j=1;j<maxnum;j++) 116 // cout<<tree[i].sum[j]<<" "; 117 // cout<<endl; 118 // }
tju oj2722