Time Limit: 2 sec / Memory Limit: 1024 MB
Score : 400 points
Problem Statement
You are given a sequence of length N: A=(A1,…,AN).
Answer QQ queries given in the following format.
- You are given integers L, R, and X. Find the number of elements among AL,…,AR whose values are equal to X.
Constraints
- 1≤N≤2×10^5
- 1≤Ai≤N
- 1≤Q≤2×10^5
- 1≤L≤R≤N,1≤X≤N, for each query.
- All values in input are integers.
Input
Input is given from Standard Input in the following format:
N A1… AN Q Query1 Query2 QueryQ
Here, \Queryi represents the i-th query.
Each query is in the following format:
L R X
Output
Print Q lines, the i-th of which contains the answer to the i-th query.
Sample Input 1 Copy
Copy
5 3 1 4 1 5 4 1 5 1 2 4 3 1 5 2 1 3 3
Sample Output 1 Copy
Copy
2 0 0 1
In the first query, two of (A1,A2,A3,A4,A5)=(3,1,4,1,5) have values equal to 1.
In the second query, zero of (A2,A3,A4)=(1,4,1) have values equal to 3.
翻译:给你n个下标从1开始的数,给出m个询问,问你在[l, r]这段区间中等于x的个数是多少。
思路:一开始觉得非常简单,直接对区间排序再二分x出现的起始和最终位置即可。时间复杂度刚好是mlogn能过,但是后来考虑到每次排序后,对下一次查询都有影响,所以应该拷贝一下,但是这样时间复杂度就成了O(n^2)过不了。
换一个思路:我们不讲每一个数存到数组中,而是存到其对应的二位数组,一维表示这个数,第二维表示它出现的下标。例如,i=2时,输入了一个9,那么我们就让q[9].push_back(2), i=4时,又读入了一个9,那么我们再push_back(4),这么我们再查询x的时候,我们只需要查询q[x]中l和r出现的位置即可,例如我们查询1-5中2出现的次数,那么我们直接在q[2]中查询一下第一个大于等于1的位置和第一个大于5的位置,这样俩个位置一减就是答案了
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200010;
vector<int> q[N];
int n, m;
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ )
{
int x;
cin >> x;
q[x].push_back(i);
}
cin >> m;
while (m -- )
{
int l, r, k;
cin >> l >> r >> k;
int a = lower_bound(q[k].begin(), q[k].end(), l) - q[k].begin();
int b = upper_bound(q[k].begin(), q[k].end(), r) - q[k].begin();
cout << b - a << endl;
}
return 0;
}