查询数组里有多少个数在[L,R]范围中(二分)

使用两次二分即可得到这个值

比如现在有一个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

查询数组里有多少个数在[L,R]范围中(二分)的相关文章

D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input standard input output standard output An array of positive integers a1,?a2,?...,?an is given. Let us consider its arbitrary subarray al,?al?+?1...,?ar, where 1?

UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)

题目链接:http://acm.upc.edu.cn/problem.php?id=2224 题意:给出n个数pi,和m个查询,每个查询给出l,r,a,b,让你求在区间l~r之间的pi的个数(A<=pi<=B,l<=i<=r). 参考链接:http://www.cnblogs.com/zj62/p/3558967.html #include <iostream> #include <cstdio> #include <cstring> #incl

【算法C++】检测数组里是否有两个数之和等于某个数

问题: 检测数组里是否有两个数之和等于某个数 解决方法一:先将数组排序,然后从两头开始遍历 数组排序后,从左端开始取最小值,从右端取最大值, 判断两者之和与目标的大小: 1. 等于时,输出两个数: 2. 大于时,右端移到第2个数,继续判断: 3. 小于时,左端移到第2个数,继续判断. #include <iostream> #include <string> #include <algorithm> using namespace std; void fun1(int

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字的最小的一个

/** * @Version 1.0.0 * 输入一个正整数数组,把数组里所有数字拼接起来排成一个数, * 打印能拼接出的所有数字的最小的一个.例如输入{3,32,321,4},则打印最小的数字是 * 321323 * * 其实就是一次排序,只是比较大小的方式与数值比较有所不同 * 这里采用冒泡排序的方式 */public class Pro33 { @MyAnswer public static void f(int array[]){ for(int i=0;i<array.length-1

查询区间内有多少个不同的数(线段树/树状数组)

入门级数据结构算法.复习一下,分别手写一个. 线段树版本(过了CF上的https://codeforces.com/contest/1291/problem/D): 1 #include<bits/stdc++.h> 2 #define f(i,a,b) for(int i=a;i<=b;i++) 3 using namespace std; 4 struct qujian{ 5 int l,r,index; 6 friend bool operator < (const quji

!HDU 5317 求区间里两个数的质因数个数的gcd的最大值-预处理

题意:设一个数i的质因数个数为F(i),现给你一个区间[l~r],求max(F[i],F[j])  数据范围:10^6 分析: 预处理出所有的F[i],O(nlgn),10^6不会超时:然后查询用O(7),查询不能用O(n),因为有多个查询会超时. 区间问题减少查询时间复杂度多半类似一个区间的和用两个前缀和相减的方式,前缀和可以在预处理的时候计算,然后区间查询是用两个前缀和相减就行了.如sum[l~r]=sum[r]-sum[l-1],再比如之前的什么我想不起来一时,想起来加上. 代码: #in

LeetCode 15 3Sum 找出数组里面3个数的和等于指定值。

题目:Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. Note: Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c) The so

计算一个数组里的重复值并且删去(java)

主要思想: 假设数字里的值都为正 循环判断数组 如果与前面的数字相同则变为-1 然后记录-1的个数算出重复值 然后重新new一个减去重复值长度的新数组 和原数组判断 不为-1的全部复制进来即可 代码如下: 1 package Del_Same_Num; 2 3 public class Del_Same_Num { 4 5 static int count=0; 6 7 //计算重复值 8 public static int count_same_number(int[] a) 9 { 10 f

HDU XXXX:求[L,R]的素数数量(数位DP)

Problem G Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/131072K (Java/Other) Total Submission(s) : 62   Accepted Submission(s) : 28 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description S number is the number wh