标签:
划分树 求一段区间第K大值
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 7 const int MAXN=100010; 8 int tree[30][MAXN]; 9 int sorted[MAXN]; 10 int toleft[30][MAXN]; 11 12 void build(int l,int r,int root) 13 { 14 if(l==r)return; 15 int mid=(l+r)>>1; 16 int same=mid-l+1; 17 for(int i=l;i<=r;i++) 18 if(tree[root][i]<sorted[mid]) 19 same--; 20 int lpos=l; 21 int rpos=mid+1; 22 for(int i=l;i<=r;i++) 23 { 24 if(tree[root][i]<sorted[mid]) 25 tree[root+1][lpos++]=tree[root][i]; 26 else if(tree[root][i]==sorted[mid]&&same>0) 27 { 28 tree[root+1][lpos++]=tree[root][i]; 29 same--; 30 } 31 else 32 tree[root+1][rpos++]=tree[root][i]; 33 toleft[root][i]=toleft[root][l-1]+lpos-l; 34 35 } 36 build(l,mid,root+1); 37 build(mid+1,r,root+1); 38 39 } 40 41 42 int query(int L,int R,int l,int r,int root,int k) 43 { 44 if(l==r)return tree[root][l]; 45 int mid=(L+R)>>1; 46 int cnt=toleft[root][r]-toleft[root][l-1]; 47 if(cnt>=k) 48 { 49 int newl=L+toleft[root][l-1]-toleft[root][L-1]; 50 int newr=newl+cnt-1; 51 return query(L,mid,newl,newr,root+1,k); 52 } 53 else 54 { 55 int newr=r+toleft[root][R]-toleft[root][r]; 56 int newl=newr-(r-l-cnt); 57 return query(mid+1,R,newl,newr,root+1,k-cnt); 58 } 59 } 60 61 62 int main() 63 { 64 int T; 65 int n,m; 66 int s,t,k; 67 scanf("%d",&T); 68 while(T--) 69 { 70 scanf("%d%d",&n,&m); 71 memset(tree,0,sizeof(tree)); 72 for(int i=1;i<=n;i++) 73 { 74 scanf("%d",&tree[0][i]); 75 sorted[i]=tree[0][i]; 76 } 77 sort(sorted+1,sorted+n+1); 78 build(1,n,0); 79 while(m--) 80 { 81 scanf("%d%d%d",&s,&t,&k); 82 printf("%d\n",query(1,n,s,t,0,k)); 83 } 84 } 85 return 0; 86 }
标签:
原文地址:http://www.cnblogs.com/airot/p/4946933.html