D. Range Count Query
题意
给一个长度为 n n n 的序列, q q q 个查询 ( l , r , x ) (l, r, x) (l,r,x),查询 ( l , r ) (l,r) (l,r)之间的 x x x的数量, n , q n,q n,q 都是 2 e 5 2e5 2e5
solution1
用莫队,对查询排序,用一个数组维护查询 ( l , r ) (l,r) (l,r) 的结果,即维护 ( l , r ) (l,r) (l,r)之间的所有数的数量,复杂度 O ( ( n + q ) ∗ s q r t ( n ) ) O((n+q)*sqrt(n)) O((n+q)∗sqrt(n))
#include <bits/stdc++.h>
using namespace std;
const int MAXM = 200005;
int n, q, A[MAXM], pos[MAXM];
typedef struct {
int l, r, id, x, ans;
}Query;
Query qe[MAXM];
int main() {
cin >> n;
int sz = sqrt(n);
for (int i = 1; i <= n; ++i) {
cin >> A[i];
pos[i] = i / sz;
}
cin >> q;
for (int i = 1; i <= q; ++i) {
cin >> qe[i].l >> qe[i].r >> qe[i].x;
qe[i].id = i;
}
sort(qe + 1, qe + 1 + q, [](Query a, Query b) {
if (pos[a.l] == pos[b.l]) return a.r < b.r;
return pos[a.l] < pos[b.l];
});
vector<int>cnt(n + 1, 0);
int l = 1, r = 0;
vector<int>v(q + 1, 0);
for (int i = 1; i <= q; ++i) {
while(l > qe[i].l) {
cnt[A[--l]]++;
}
while(r < qe[i].r) {
cnt[A[++r]]++;
}
while(l < qe[i].l) {
cnt[A[l++]]--;
}
while(r > qe[i].r) {
cnt[A[r--]]--;
}
v[qe[i].id] = cnt[qe[i].x];
// cout << l <<" " << r << " " << qe[i].l <<" " << qe[i].r << endl;
// for (int j = 1; j <= n; j++)
// cout << cnt[j] << " ";
// cout << endl;
}
for (int i = 1; i <= q; ++i)
cout << v[i] << endl;
}
solution2
对于整个序列中出现的每个数字用一个 vector 存这个数字出现的位置,然后查询的时候,对 x x x 的那个 vector 进行二分。复杂度 O ( n + q l o g n ) O(n+qlogn) O(n+qlogn)
#include <bits/stdc++.h>
using namespace std;
const int MAXM = 200005;
int n, q, A[MAXM];
vector<int>pos[MAXM];
int main() {
cin >> n;
int sz = sqrt(n);
for (int i = 1; i <= n; ++i) {
cin >> A[i];
pos[A[i]].push_back(i);
}
cin >> q;
for (int i = 1; i <= q; i++) {
int l, r, x;
cin >> l >> r >> x;
int ans = upper_bound(pos[x].begin(), pos[x].end(), r) - lower_bound(pos[x].begin(), pos[x].end(), l);
cout << ans << endl;
}
}