题意

给定一个长度为 的数组, 次询问查询区间 的元素个数。

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