题目
题解
莫队板子题
- 普通莫队的操作
- 将询问排序
- 定义L,R指针跳到询问区间
- 排序方式
将整个区间分为不同块,块长为 n m \frac{n}{\sqrt{m}} mn有的大佬说是 n \sqrt{n} n但是推一下就知道 n m \frac{n}{\sqrt{m}} mn更合理 - 指针跳动 这个应该很好理解吧
- 跳动时答案统计方式(看代码理解吧)
c n t [ i ] cnt[i] cnt[i]表示颜色为 i i i出现的次数
#include <bits/stdc++.h>
using namespace std;
//const int maxn = 3e4 + 1000;
//const int maxc = 1e6 + 1000;
const int maxm = 5e6 + 1000;
template <typename T>
inline void read(T &s) {
s = 0;
T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
int n, m, k, blo, ans;
int a[maxm], cnt[maxm], res[maxm], belong[maxm];
struct query { int l, r, id; } q[maxm];
/*inline bool cmp(query aa, query bb) {
return (belong[aa.l] == belong[bb.l]) ? aa.r < bb.r : aa.l < bb.l;
}*/
inline bool cmp(query aa, query bb){
return belong[aa.l] ^ belong[bb.l] ? belong[aa.l] < belong[bb.l] : belong[aa.l] & 1 ? aa.r < bb.r : aa.r > bb.r;
}
//inline void add(int x) { if (!cnt[ a[x] ]) ans++; ++cnt[ a[x] ]; }
//inline void del(int x) { --cnt[ a[x] ]; if (!cnt[ a[x] ]) ans--; }
//inline void add(int x) { if (!cnt[ a[x] ]++) ans++; }
//inline void del(int x) { if (!--cnt[ a[x] ]) ans--; }
int main() {
read(n);
blo = sqrt(n);
for (int i = 1; i <= n; ++i)
read(a[i]), belong[i] = (i - 1) / blo + 1;
read(m);
// blo = n / sqrt(m);
for (int i = 1; i <= m; ++i) {
read(q[i].l), read(q[i].r);
q[i].id = i;
}
sort(q + 1, q + m + 1, cmp);
int l = 1, r = 0;
for (int i = 1; i <= m; ++i) {
int ql = q[i].l, qr = q[i].r;
// while (l < ql) del(l++);
// while (l > ql) add(--l);
// while (r > qr) del(r--);
// while (r < qr) add(++r);
while (l < ql) ans -= !--cnt[ a[l++] ];
while (l > ql) ans += !cnt[ a[--l] ]++;
while (r > qr) ans -= !--cnt[ a[r--] ];
while (r < qr) ans += !cnt[ a[++r] ]++;
res[ q[i].id ] = ans;
}
for (int i = 1; i <= m; ++i) {
printf("%d\n", res[i]);
}
return 0;
}