hdu 4117 Super Mario

题目描述

  给定一个序列,询问某段区间内小于等于k的数的个数。

分析

  划分树+二分,二分的同时统计满足题意的数的个数。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define N 100100
 5 #define lson l,m,n<<1
 6 #define rson m+1,r,n<<1|1
 7 using namespace std;
 8 int sorted[N],ans[N][20],num[N][20];
 9 void build(int l,int r,int n,int d){
10     if(l==r)return;
11     int m=(l+r)>>1,lsame=m-l+1;
12     for(int i=l;i<=r;i++)
13     if(ans[i][d]<sorted[m]) lsame--;
14     int lpos=l,rpos=m+1;
15     for(int i=l;i<=r;i++){
16         if(i==l) num[i][d]=0;
17         else num[i][d]=num[i-1][d];
18         if(ans[i][d]<sorted[m]){
19             num[i][d]++;
20             ans[lpos++][d+1]=ans[i][d];
21         }
22         else if(ans[i][d]>sorted[m])
23         ans[rpos++][d+1]=ans[i][d];
24         else{
25             if(lsame>0){
26                 lsame--;
27                 num[i][d]++;
28                 ans[lpos++][d+1]=ans[i][d];
29             }
30             else
31             ans[rpos++][d+1]=ans[i][d];
32         }
33     }
34     build(lson,d+1);
35     build(rson,d+1);
36 }
37 //求区间第k小的数
38 int query(int ll,int rr,int k,int l,int r,int n,int d){
39     if(l==r)return ans[l][d];
40     int s,ss;
41     int m=(l+r)>>1;
42     if(ll==l) s=0;
43     else s=num[ll-1][d];
44     ss=num[rr][d]-s;
45     if(ss>=k)
46     return query(l+s,l+s+ss-1,k,lson,d+1);
47     else{
48         int xx,x;
49         xx=ll-l-s;
50         x=rr-ll+1-ss;
51         return query(m+xx+1,m+x+xx,k-ss,rson,d+1);
52     }
53 }
54 int n,m,t;
55 int BS(int l,int r,int key){
56     int ll=1,rr=r-l+1;
57     int ans=0;
58     while(ll<=rr){
59         int m=(ll+rr)>>1;
60         int x=query(l,r,m,1,n,1,1);
61         if(key>=x){
62             ans+=(m-ll+1);
63             ll=m+1;
64         }
65         else if(key<x) rr=m-1;
66     }
67     return ans;
68 }
69 int main(){
70     int d=1;
71     scanf("%d",&t);
72     while(t--){
73         scanf("%d%d",&n,&m);
74         for(int i=1;i<=n;i++){
75             scanf("%d",&sorted[i]);
76             ans[i][1]=sorted[i];
77         }
78         sort(sorted+1,sorted+1+n);
79         build(1,n,1,1);
80         printf("Case %d:\n",d++);
81         while(m--){
82             int l,r,k;
83             scanf("%d%d%d",&l,&r,&k);l++;r++;
84             printf("%d\n",BS(l,r,k));
85     }
86     }
87     return 0;
88 }
posted @ 2012-10-08 19:42  silver__bullet  阅读(131)  评论(0编辑  收藏  举报