SPOJ - DQUERY(区间不同数+树状数组)
题意:求给定区间不同数的个数(不更新)。
题解:离线+树状数组。
对所求的所有区间(l, r)根据r从小到大排序。从1-n依次遍历序列数组,在树状数组中不断更新a[i]出现的最后一个位置。更新:将a[i]所在位置i在树状数组中加1(add(i, 1)),并消去a[i]上次出现的位置上的1(add(lasta[i], -1))。当遍历到i == r时,就保存答案(sum[r] - sum[l-1])。
#include<bits/stdc++.h> using namespace std; const int maxn = 2e6 + 10; int n, q; int a[maxn]; int bit[maxn]; struct Node{ int l, r, id; bool operator < (const Node& A) const { return r < A.r; } }p[maxn]; int last[maxn]; int ans[maxn]; void add(int i, int x) { while(i > 0 && i < maxn){ bit[i] += x; i += i & -i; } } int sum(int i) { int ans = 0; while(i){ ans += bit[i]; i -= i & -i; } return ans; } int main() { while(scanf("%d", &n) != EOF){ memset(bit, 0, sizeof(bit)); memset(last, -1, sizeof(last)); int tot = 0; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); scanf("%d", &q); for(int i = 0; i < q; i++){ scanf("%d%d", &p[i].l, &p[i].r); p[i].id = i; } sort(p, p + q); //区间排序 memset(ans, 0, sizeof(ans)); for(int i = 1, k = 0; i <= n; i++){ //更新a[i]出现的最后一个位置 if(last[a[i]] != -1){ add(last[a[i]], -1); add(i, 1); last[a[i]] = i; } else{ last[a[i]] = i; add(i, 1); } //保存答案 while(k < q && p[k].r == i){ ans[p[k].id] = sum(p[k].r) - sum(p[k].l - 1); k++; } } for(int i = 0; i < q; i++) printf("%d\n", ans[i]); } }

浙公网安备 33010602011771号