HDU 4417 Super Mario(划分树)

 

题目大意

 

给你 n(1<=n<=10^5) 个数,m(1<=m<=10^5) 个询问,每个询问的格式如下

L R H:从第 L 个数到第 R 个数中,小于等于 H 的数有多少个

 

做法分析

 

建立划分树

每次 query 的时候,二分答案即可,即二分这个区间中有多少个小于等于 H 的数

 

参考代码

 

HDU 4417
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 const int N=100006;
 9 
10 struct devided_tree
11 {
12     int val[20][N], f[20][N], sorted[N];
13 
14     void build(int L, int R, int deep)
15     {
16         if(L==R) return;
17         int mid=(L+R)>>1;
18         int midVal=sorted[mid], tot=mid-L+1;
19         for(int i=L; i<=R; i++) if(val[deep][i]<midVal) tot--;
20         int sL=L, sR=mid+1;
21         for(int i=L; i<=R; i++)
22         {
23             f[deep][i]=(i==L)?0:f[deep][i-1];
24             if(val[deep][i]<midVal || (val[deep][i]==midVal && tot))
25             {
26                 val[deep+1][sL++]=val[deep][i];
27                 f[deep][i]++;
28                 if(val[deep][i]==midVal) tot--;
29             }
30             else val[deep+1][sR++]=val[deep][i];
31         }
32         build(L, mid, deep+1), build(mid+1, R, deep+1);
33     }
34 
35     int query(int L, int R, int st, int en, int k, int deep)
36     {
37         if(st==en) return val[deep][st];
38         int mid=(L+R)>>1;
39         int L1=(L==st)?0:f[deep][st-1];
40         int L2=f[deep][en]-L1;
41         if(k<=L2) return query(L, mid, L+L1, L+L1+L2-1, k, deep+1);
42         int R1=(st-1-L+1)-L1;
43         int R2=(en-st+1)-L2;
44         return query(mid+1, R, mid+1+R1, mid+1+R1+R2-1, k-L2, deep+1);
45     }
46 } tree;
47 
48 int main()
49 {
50     int t, n, m;
51     scanf("%d", &t);
52     for(int ca=1; ca<=t; ca++)
53     {
54         scanf("%d%d", &n, &m);
55         for(int i=0; i<n; i++)
56         {
57             scanf("%d", &tree.val[0][i]);
58             tree.sorted[i]=tree.val[0][i];
59         }
60         sort(tree.sorted, tree.sorted+n);
61         tree.build(0, n-1, 0);
62         printf("Case %d:\n", ca);
63         for(int i=0, a, b, c; i<m; i++)
64         {
65             scanf("%d%d%d", &a, &b, &c);
66             int L=1, R=b-a+1;
67             while(L<R)
68             {
69                 int mid=(L+R)>>1;
70                 int keyVal=tree.query(0, n-1, a, b, mid, 0);
71                 if(keyVal<=c) L=mid+1;
72                 else R=mid;
73             }
74             if(tree.query(0, n-1, a, b, L, 0)>c) L--;
75             printf("%d\n", L);
76         }
77     }
78     return 0;
79 }

 

AC通道

 

HDU 4417 Super Mario

 

 

 

posted @ 2013-03-17 00:40  jianzhang.zj  阅读(156)  评论(0编辑  收藏  举报