使用两次二分即可得到这个值
比如现在有一个vector<int> vec,里面存放的是有序数列。
我们现在希望找出范围在[L,R]之间的数有多少个。
则有cnt = upper_bound(vec.begin(),vec.end(),r) - lower_bound( vec.begin(),vec.end(),l)
这么多个。
比如这个题就可以用二分http://codeforces.com/problemset/problem/220/B
代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 int n,m; 6 vector<int> pos[1111]; 7 const int MAX_N = 1e5+100; 8 int cnt[MAX_N],a[MAX_N]; 9 int vis[MAX_N],fc[1111]; 10 11 int main(){ 12 scanf("%d%d",&n,&m); 13 for(int i=1;i<=n;i++){ 14 scanf("%d",&a[i]); 15 } 16 for(int i=1;i<=n;i++){ 17 if( a[i]<=100000 ){ 18 cnt[a[i]]++; 19 } 20 } 21 22 int now = 1; 23 vector<int> num; 24 for(int i=1;i<=100000;i++){ 25 if( cnt[i]>=i ){ 26 fc[now] = i; 27 vis[i] = now++; 28 num.push_back(i); 29 } 30 } 31 for(int i=0;i<1111;i++) pos[i].push_back(0); 32 for(int i=1;i<=n;i++){ 33 if(a[i]>100000) continue; 34 int id = vis[a[i]]; 35 if( id ){ 36 pos[id].push_back(i); 37 } 38 } 39 // for(int i=1;i<=3;i++){ 40 // printf("%d:",i); 41 // for(int j=0;j<pos[i].size();j++){ 42 // printf(" %d",pos[i][j]); 43 // } 44 // puts(""); 45 // } 46 // printf("now = %d\n",now); 47 typedef vector<int>::iterator pt; 48 while(m--){ 49 int l,r; 50 scanf("%d%d",&l,&r); 51 // printf("l=%d,r=%d\n",l,r); 52 int ans = 0; 53 for(int i=1;i<now;i++){ 54 int nnn = fc[i]; 55 pt it1= upper_bound(pos[i].begin(),pos[i].end(),r); 56 pt it2= lower_bound(pos[i].begin(),pos[i].end(),l); 57 int cntt = it1-it2; 58 // printf("cntt=%d\n",cntt); 59 if( cntt==nnn ){ 60 ans++; 61 } 62 } 63 printf("%d\n",ans); 64 } 65 66 return 0; 67 }
时间: 2024-10-12 23:11:26