题目
思路
莫队+树状数组,树状数组维护数出现的次数和是否出现过。
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001
#define lowbit(x) x & (-x)
int n, m, sqrn, a[M], num[M], ans1[M], ans2[M], cnt[M];
struct Query {
int x, y, lm, rm, id;
friend bool operator < (Query q1, Query q2) {
if (num[q1.x] == num[q2.x]) return q1.y < q2.y;
return num[q1.x] < num[q2.x];
}
}q[M];
struct BIT {
int c[M];
void add(int x, int k) {
for (; x <= n; x += lowbit(x)) c[x] += k;
}
int ask(int x) {
int res = 0;
for (; x > 0; x -= lowbit(x)) res += c[x];
return res;
}
}bt1, bt2;
void add(int x) {
++cnt[x], bt1.add(x, 1);
if (cnt[x] == 1) bt2.add(x, 1);
}
void del(int x) {
--cnt[x], bt1.add(x, -1);
if (cnt[x] == 0) bt2.add(x, -1);
}
int main() {
scanf("%d %d", &n, &m), sqrn = n / sqrt(m);
if (!sqrn) ++sqrn;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
num[i] = (i - 1) / sqrn + 1;
}
for (int i = 1; i <= m; ++i) {
scanf("%d %d %d %d", &q[i].x, &q[i].y, &q[i].lm, &q[i].rm);
q[i].id = i;
}
std::sort(q + 1, q + m + 1);
int l = 1, r = 1; cnt[a[1]] = 1;
bt1.add(a[1], 1), bt2.add(a[1], 1);
for (int i = 1; i <= m; ++i) {
while (l > q[i].x) add(a[--l]);
while (r < q[i].y) add(a[++r]);
while (l < q[i].x) del(a[l++]);
while (r > q[i].y) del(a[r--]);
ans1[q[i].id] = bt1.ask(q[i].rm) - bt1.ask(q[i].lm - 1);
ans2[q[i].id] = bt2.ask(q[i].rm) - bt2.ask(q[i].lm - 1);
}
for (int i = 1; i <= m; ++i) {
printf("%d %d
", ans1[i], ans2[i]);
}
return 0;
}