莫队算法
DQUERY
Given a sequence of n numbers a1, a2, …, an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai+1, …, aj.
解法
离线修改查询次序,莫队。 之前写的挫,看到这个写的比较好。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int SIZE = 300005;
const int CSIZE = 1000005;
const int BLOCK = 555;
int cnt[CSIZE], a[SIZE], res[SIZE], ans;
struct node {
int L, R, i;
} q[SIZE];
bool cmp(const node &x, const node &y) {
if(x.L/BLOCK != y.L/BLOCK) return x.L/BLOCK < y.L/BLOCK;
return x.R < y.R;
}
void add(int pos) {
cnt[a[pos]]++;
if(cnt[a[pos]] == 1) ans++;
}
void remove(int pos) {
cnt[a[pos]]--;
if(!cnt[a[pos]]) ans--;
}
int main() {
int N;
scanf("%d",&N);
for(int i = 1; i <= N; i++) scanf("%d",&a[i]);
int Q;
scanf("%d",&Q);
for(int i = 1; i <= Q; i++) {
scanf("%d%d",&q[i].L, &q[i].R);
q[i].i = i;
}
sort(q + 1, q + 1 + Q, cmp);
int l = 1, r = 1;
for(int i = 1; i <= Q; i++) {
int L = q[i].L, R = q[i].R;
while(l < L) remove(l++);
while(l > L) add((l--) - 1);
while(r <= R) add(r++);
while(r > R+1) remove((r--) - 1);
res[q[i].i] = ans;
}
for(int i = 1; i <= Q; i++) printf("%d\n",res[i]);
}