SPOJ 3267 求区间不同数的个数

时间:2023-03-09 18:47:24
SPOJ 3267 求区间不同数的个数

题意:给定一个数列,每次查询一个区间不同数的个数。

做法:离线+BIT维护。将查询按右端点排序。从左到右扫,如果该数之前出现过,则将之前出现过的位置相应删除;当前位置则添加1。这样做就保证每次扫描到的某一位置,以该位置为右端点的区间都相应地确定了。

 /*
*Author: Zhaofa Fang
*Created time: 2013-08-25-22.29 星期日
*/
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std; typedef long long ll;
typedef pair<int,int> PII;
#define DEBUG(x) cout<< #x << ':' << x << endl
#define FOR(i,s,t) for(int i = (s);i <= (t);i++)
#define FORD(i,s,t) for(int i = (s);i >= (t);i--)
#define REP(i,n) for(int i=0;i<(n);i++)
#define REPD(i,n) for(int i=(n-1);i>=0;i--)
#define PII pair<int,int>
#define PB push_back
#define ft first
#define sd second
#define lowbit(x) (x&(-x))
#define INF (1<<30)
#define eps (1e-8) const int maxq = ;
const int maxn = ;
int a[maxn],C[maxn],last[];
int ans[maxq];
void init(){
memset(C,,sizeof(C));
memset(last,-,sizeof(last));
}
struct Query{
int l,r;
int idx;
bool operator < (const Query & rhs)const{
return r < rhs.r;
}
}Q[maxq]; void add(int x,int val){
while(x<maxn){
C[x] += val;
x += lowbit(x);
}
}
int sum(int x){
int res = ;
while(x > ){
res += C[x];
x -= lowbit(x);
}
return res;
}
int main(){
//freopen("in","r",stdin);
//freopen("out","w",stdout);
int n;
while(~scanf("%d",&n)){
init();
FOR(i,,n)scanf("%d",&a[i]);
int q;
scanf("%d",&q);
REP(i,q){
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].idx = i;
}
sort(Q,Q+q);
int pre = ;
REP(i,q){
FOR(j,pre,Q[i].r){
if(last[a[j]]==-){
add(j,);
}else {
add(last[a[j]],-);
add(j,);
}
last[a[j]] = j;
}
ans[Q[i].idx] = sum(Q[i].r)-sum(Q[i].l-);
pre = Q[i].r+;
}
REP(i,q)printf("%d\n",ans[i]);
}
return ;
}