hdu4417(权值离散化后建立主席树)

Problem - 4417 (hdu.edu.cn)

马里奥是举世闻名的水管工。他“魁梧”的身材和惊人的跳跃能力让我们想起了。现在可怜的公主又遇到了麻烦,马里奥需要拯救他的爱人。我们将通往老板城堡的道路视为一条线(长度为 n),在每个整数点 i 上都有一块高度为 hi 的砖。现在的问题是,如果马里奥可以跳跃的最大高度是 H,那么 [L, R] 马里奥可以击中多少块砖。

输入

第一行后面跟着一个整数 T,即测试数据的数量。
对于每个测试数据:
第一行包含两个整数n,m(1<=n<=10^5,1<=m<=10^5),n是道路的长度,m是查询的次数。
下一行包含 n 个整数,每个砖的高度,范围为 [0, 1000000000]。
接下来的 m 行,每行包含三个整数 L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000。

输出

对于每个案例,输出“Case X:”(X 是从 1 开始的案例编号),后跟 m 行,每行包含一个整数。第 i 个整数是 Mario 可以在第 i 个查询中击中的砖块数。

思路

目标是找到查询区间[L,R]中比H小或者等于的数有多少个,那我们可以对数组离散化后建立权值主席树,sum数组表示对应权值[l,r]区间中的包含的已有数的个数,后续操作就比较常规了。

 1 #define IO std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
 2 #define bug(x) cout<<#x<<" is "<<x<<endl
 3 #include <iostream>
 4 #include <list>
 5 #include <unordered_map>
 6 #include <map>
 7 #include <vector>
 8 #include <sstream>
 9 #include <cmath>
10 #include <algorithm>
11 #define iter ::iterator
12 using namespace  std;
13 typedef long long ll;
14 typedef pair<int,int>P;
15 #define pb push_back
16 #define mk make_pair
17 #define se second
18 #define fi first
19 
20 const ll mod=1e9+7;
21 const int N=1e5+5;
22 int n,q;
23 int a[N],b[N],rt[N*32],ls[N*32],rs[N*32],sum[N*32];
24 int cnt;
25 void up(int &o,int pre,int l,int r,int val){
26     o=++cnt;
27     ls[o]=ls[pre];
28     rs[o]=rs[pre];
29     sum[o]=sum[pre]+1;
30     if(l==r)return;
31     int m=(l+r)/2;
32     if(val<=m)up(ls[o],ls[pre],l,m,val);
33     else up(rs[o],rs[pre],m+1,r,val);
34 }
35 int qu(int o,int pre,int l,int r,int val){
36 
37     int res=sum[o]-sum[pre];
38     //printf("%d %d %d\n",l,r,res);
39     if(r<=val)return res;
40     if(l>val)return 0;
41     if(l==r)return res;
42     int m=(l+r)/2;
43     res=qu(ls[o],ls[pre],l,m,val);
44     if(val>m)res+=qu(rs[o],rs[pre],m+1,r,val);
45     return res;
46 }
47 int main(){
48     IO;
49     int T,Case=0;
50     cin>>T;
51     while(T--){
52         cnt=0;
53         cin>>n>>q;
54         
55         for(int i=0;i<n;i++)cin>>a[i],b[i]=a[i];
56         sort(a,a+n);
57         int m=unique(a,a+n)-a;
58         for(int i=0;i<n;i++) b[i]=lower_bound(a,a+m,b[i])-a+1;
59         for(int i=1;i<=n;i++){
60             up(rt[i],rt[i-1],1,m,b[i-1]);
61         }
62         cout<<"Case "<<++Case<<":"<<endl;
63         while(q--){
64             int L,R,val;
65             cin>>L>>R>>val;
66             int x=val;
67             val=lower_bound(a,a+m,val)-a+1;
68             if(a[val-1]!=x)val--;
69             cout<<qu(rt[R+1],rt[L],1,m,val)<<endl;
70         }
71         printf("\n");
72     }
73 }

 

posted @ 2024-05-22 15:11  Venux  阅读(3)  评论(0编辑  收藏  举报