D - Range Count Query

原题链接

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值