SPOJ - DQUERY(区间不同数+树状数组)

时间:2023-03-10 02:38:46
SPOJ - DQUERY(区间不同数+树状数组)

链接: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 + ;
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 > && i < maxn){
bit[i] += x;
i += i & -i;
}
} int sum(int i)
{
int ans = ;
while(i){
ans += bit[i];
i -= i & -i;
}
return ans;
} int main()
{
while(scanf("%d", &n) != EOF){ memset(bit, , sizeof(bit));
memset(last, -, sizeof(last));
int tot = ;
for(int i = ; i <= n; i++) scanf("%d", &a[i]);
scanf("%d", &q);
for(int i = ; i < q; i++){
scanf("%d%d", &p[i].l, &p[i].r);
p[i].id = i;
}
sort(p, p + q); //区间排序 memset(ans, , sizeof(ans));
for(int i = , k = ; i <= n; i++){
//更新a[i]出现的最后一个位置
if(last[a[i]] != -){
add(last[a[i]], -);
add(i, );
last[a[i]] = i;
}
else{
last[a[i]] = i;
add(i, );
} //保存答案
while(k < q && p[k].r == i){
ans[p[k].id] = sum(p[k].r) - sum(p[k].l - );
k++;
}
} for(int i = ; i < q; i++) printf("%d\n", ans[i]);
}
}