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 }

 

你可能感兴趣的:(HDU)