1. 程式人生 > 實用技巧 >查詢區間裡有多少個小於k的數

查詢區間裡有多少個小於k的數

用主席樹可以線上做,樹狀陣列只能離線。

先放個主席樹的。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<queue>
 5 #include<set>
 6 #include<string>
 7 #include<cmath>
 8 #include<cstring>
 9 #define FF first
10 #define SS second
11 #define ll long long
12
#define pb push_back 13 #define pm make_pair 14 using namespace std; 15 typedef pair<int,int> PII; 16 const int MAX = 1e5 + 5; 17 struct TREE { 18 int l,r; 19 int val; 20 } tr[MAX*40]; 21 22 int tot; 23 int a[MAX],b[MAX]; 24 int root[MAX]; 25 int build(int l,int r) { 26 int cur = ++tot;
27 tr[cur].val = 0; 28 if(l == r) { 29 tr[cur].l = tr[cur].r = 0;//這一步好像沒啥用? 30 return cur; 31 } 32 int m = (l+r)>>1; 33 tr[cur].l = build(l,m); 34 tr[cur].r = build(m+1,r); 35 return cur; 36 } 37 void pushup(int cur) { 38 tr[cur].val = tr[tr[cur].l].val + tr[tr[cur].r].val;
39 } 40 int update(int pre,int tar,int l,int r) { 41 int cur = ++tot; 42 tr[cur] = tr[pre]; 43 if(l == r) { 44 tr[cur].val++; 45 return cur; 46 } 47 int m = (l+r)>>1; 48 if(tar <= m) tr[cur].l = update(tr[pre].l,tar,l,m); 49 else tr[cur].r = update(tr[pre].r,tar,m+1,r); 50 pushup(cur); 51 return cur; 52 } 53 int query(int pl,int pr,int l,int r,int H) { 54 if(l == r) return tr[pr].val - tr[pl].val; 55 int m = (l+r)>>1; 56 if(H <= m) return query(tr[pl].l,tr[pr].l,l,m,H); 57 else return tr[tr[pr].l].val - tr[tr[pl].l].val + query(tr[pl].r,tr[pr].r,m+1,r,H); 58 } 59 int main() 60 { 61 int n,m; 62 int t,iCase=0; 63 cin>>t; 64 while(t--) { 65 printf("Case %d:\n",++iCase); 66 cin>>n>>m; 67 tot=0; 68 for(int i = 1; i<=n; i++) scanf("%d",a+i),b[i] = a[i]; 69 root[0] = build(1,n); 70 sort(b+1,b+n+1); 71 int LEN = unique(b+1,b+n+1) - b - 1; 72 for(int i = 1; i<=n; i++) { 73 int pos = lower_bound(b+1,b+LEN+1,a[i]) - b; 74 root[i] = update(root[i-1],pos,1,n); 75 } 76 while(m--) { 77 int l,r,H; 78 scanf("%d%d%d",&l,&r,&H);l++,r++; 79 int pos = upper_bound(b+1,b+LEN+1,H) - b - 1; 80 if(pos) printf("%d\n",query(root[l-1],root[r],1,n,pos)); 81 else printf("0\n"); 82 } 83 } 84 return 0 ; 85 }

再放一個樹狀陣列的。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxm=1e5+5;
 8 struct Data{
 9     int num,id;
10     bool operator<(const Data a){//按數值大小排序
11         return num<a.num;
12     }
13 }a[maxm];
14 struct Query{
15     int l,r,h,id;
16     bool operator<(const Query a){//按h排序
17         return h<a.h;
18     }
19 }q[maxm];
20 int c[maxm];//BIT
21 int res[maxm];//存答案
22 int n,m;
23 int cas=1;
24 void init(){
25     memset(c,0,sizeof c);
26 }
27 int lowbit(int i){
28     return i&-i;
29 }
30 void add(int i,int x){
31     while(i<=n){
32         c[i]+=x;
33         i+=lowbit(i);
34     }
35 }
36 int ask(int i){
37     int ans=0;
38     while(i){
39         ans+=c[i];
40         i-=lowbit(i);
41     }
42     return ans;
43 }
44 void input(){
45     scanf("%d%d",&n,&m);
46     for(int i=1;i<=n;i++){
47         scanf("%d",&a[i].num);
48         a[i].id=i;
49     }
50     for(int i=1;i<=m;i++){
51         scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h);
52         q[i].l++,q[i].r++;//題目區間從0開始,加1變為從1開始
53         q[i].id=i;
54     }
55     sort(a+1,a+1+n);
56     sort(q+1,q+1+m);
57 }
58 void solve(){
59     printf("Case %d:\n",cas++);
60     int last=1;
61     for(int i=1;i<=m;i++){
62         while(q[i].h>=a[last].num&&last<=n){//把數值比h小的插入
63             add(a[last].id,1);//插入的是編號
64             last++;
65         }
66         res[q[i].id]=ask(q[i].r)-ask(q[i].l-1);
67     }
68     for(int i=1;i<=m;i++){
69         printf("%d\n",res[i]);
70     }
71 }
72 int main(){
73     int T;
74     scanf("%d",&T);
75     while(T--){
76         init();
77         input();
78         solve();
79     }
80     return 0;
81 }

HDU 4417,板題。