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("*****
");
 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:
",ca);
109         while(m--)
110         {
111             scanf("%d%d%d",&s,&t,&h);
112             s++;
113             t++;
114             printf("%d
",solve(n,s,t,h));
115         }
116     }
117     return 0;
118 }
原文地址:https://www.cnblogs.com/cnblogs321114287/p/4393687.html