题意
给定一个长度为 的数组, 次询问查询区间 内 的元素个数。
solution
考虑树状数组。我们在查询区间 的个数时,为了更好计数,这个区间应该不包含 的元素才行。因此我们不妨离线,将询问的 从小到大排序,将数组也从小到大排序,这样从小到大处理询问,每次处理时只将 的数挂到树的对应下标上(因为询问的 是从小到大的,因此之前树上的数一定比当前询问的 要小),维护答案为 。
Code
#include <bits/stdc++.h> #define x first #define y second using namespace std; const int N = 2e5 + 5; struct Node { int l, r, v, id; } q[N]; int n, m, c[N], res[N]; pair<int, int> p[N]; bool cmp(Node x, Node y) { return x.v < y.v; } void update(int x) { for (; x <= n; x += x & (-x)) c[x]++; } int query(int x) { int sum = 0; for (; x >= 1; x -= x & (-x)) sum += c[x]; return sum; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> p[i].x; p[i].y = i; } sort(p + 1, p + n + 1); for (int i = 1; i <= m; i++) { cin >> q[i].l >> q[i].r >> q[i].v; q[i].id = i; } sort(q + 1, q + m + 1, cmp); int pos = 1; for (int i = 1; i <= m; i++) { while (q[i].v >= p[pos].x && pos <= n) { update(p[pos].y); pos++; } res[q[i].id] = query(q[i].r) - query(q[i].l - 1); } for (int i = 1; i <= m; i++) cout << res[i] << '\n'; return 0; }