hdu 4417 区间内比h小的数 划分树
二分查找最近一个比h小的数
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 #define for0n for(i=0;i<n;i++) 9 #define for1n for(i=1;i<=n;i++) 10 #define for0m for(i=0;i<m;i++) 11 #define for1m for(i=1;i<=m;i++) 12 #define cl(a) memset(a,0,sizeof(a)) 13 #define w12 while(scanf("%d%d",&n,&m)!=EOF) 14 #define s12 scanf("%d%d",&n,&m); 15 #define sa scanf("%d",a[i]); 16 #define sb scanf("%d",b[i]); 17 #define qq printf("*****\n"); 18 const int maxn=1005; 19 int n,m,tt; 20 const int MAXN = 100010; 21 int tree[20][MAXN];//表示每层每个位置的值 22 int sorted[MAXN];//已经排序好的数 23 int toleft[20][MAXN];//toleft[p][i]表示第i层从1到i有数分入左边 24 void build(int l,int r,int dep) 25 { 26 if(l == r)return; 27 int mid = (l+r)>>1; 28 int same = mid - l + 1;//表示等于中间值而且被分入左边的个数 29 for(int i = l; i <= r; i++) //注意是l,不是one 30 if(tree[dep][i] < sorted[mid]) 31 same--; 32 int lpos = l; 33 int rpos = mid+1; 34 for(int i = l;i <= r;i++) 35 { 36 if(tree[dep][i] < sorted[mid]) 37 tree[dep+1][lpos++] = tree[dep][i]; 38 else if(tree[dep][i] == sorted[mid] && same > 0) 39 { 40 tree[dep+1][lpos++] = tree[dep][i]; 41 same--; 42 } 43 else 44 tree[dep+1][rpos++] = tree[dep][i]; 45 toleft[dep][i] = toleft[dep][l-1] + lpos - l; 46 } 47 build(l,mid,dep+1); 48 build(mid+1,r,dep+1); 49 } 50 //查询区间第k大的数,[L,R]是大区间,[l,r]是要查询的小区间 51 int query(int L,int R,int l,int r,int dep,int k) 52 { 53 if(l == r)return tree[dep][l]; 54 int mid = (L+R)>>1; 55 int cnt = toleft[dep][r] - toleft[dep][l-1]; 56 if(cnt >= k) 57 { 58 int newl = L + toleft[dep][l-1] - toleft[dep][L-1]; 59 int newr = newl + cnt - 1; 60 return query(L,mid,newl,newr,dep+1,k); 61 } 62 else 63 { 64 int newr = r + toleft[dep][R] - toleft[dep][r]; 65 int newl = newr - (r-l-cnt); 66 return query(mid+1,R,newl,newr,dep+1,k-cnt); 67 } 68 } 69 int solve(int n,int s,int t,int h) 70 { 71 int l=1; 72 int r=(t-s)+1; 73 int ans=0; 74 while(l<=r) 75 { 76 int mid=((l+r)>>1); 77 int tp=query(1,n,s,t,0,mid); 78 if(tp<=h) 79 { 80 ans=mid; 81 l=mid+1; 82 } 83 else r=mid-1; 84 } 85 return ans; 86 } 87 int main() 88 { 89 #ifndef ONLINE_JUDGE 90 freopen("1.in","r",stdin); 91 #endif 92 int i,j,k,h; 93 scanf("%d",&tt); 94 int ca=0; 95 while(tt--) 96 { 97 ca++; 98 s12; 99 memset(tree,0,sizeof(tree)); 100 for(i = 1;i <= n;i++) 101 { 102 scanf("%d",&tree[0][i]); 103 sorted[i] = tree[0][i]; 104 } 105 sort(sorted+1,sorted+n+1); 106 build(1,n,0); 107 int s,t,k; 108 printf("Case %d:\n",ca); 109 while(m--) 110 { 111 scanf("%d%d%d",&s,&t,&h); 112 s++; 113 t++; 114 printf("%d\n",solve(n,s,t,h)); 115 } 116 } 117 return 0; 118 }