在线做法(只面对kind_num ≤ 60):
使用线段树维护,把种类压成一个二进制,每次pushup取或就可以了。
离线做法:见代码或他人题解!不会说!
#include <cstdio>
#include <algorithm>
using namespace std;
inline char gc() {
static char now[1<<16], *S, *T;
if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}
return *S++;
}
inline int read() {
int x = 0; char c = gc();
while(c < '0' || c > '9') c = gc();
while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = gc();}
return x;
}
struct Query {int l, r, id;}q[200010];
int a[50010], pos[1000010], las[50010], BIT[50010], ans[200010];
int n, m;
inline bool cmp(Query A, Query B) {return A.r < B.r;}
inline void add(int x, int v) {for(; x <= n; x+= x & -x) BIT[x]+= v;}
inline int query(int x) {int ret = 0; for(; x; x-= x & -x) ret+= BIT[x]; return ret;}
int main() {
n = read(); for(int i = 1; i <= n; ++i) a[i] = read();
for(int i = 1; i <= n; ++i) las[i] = pos[a[i]], pos[a[i]] = i;
m = read();
for(int i = 1; i <= m; ++i) {q[i].l = read(); q[i].r = read(); q[i].id = i;}
sort(q+1, q+m+1, cmp); int cur = 0;
for(int i = 1; i <= m; ++i) {
while(cur < q[i].r) {
++cur;
add(cur, 1); if(las[cur]) add(las[cur], -1);
}
ans[q[i].id] = query(q[i].r) - query(q[i].l - 1);
}
for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
return 0;
}