题意:给定一个数列,每次查询一个区间不同数的个数。
做法:离线+BIT维护。将查询按右端点排序。从左到右扫,如果该数之前出现过,则将之前出现过的位置相应删除;当前位置则添加1。这样做就保证每次扫描到的某一位置,以该位置为右端点的区间都相应地确定了。
1 /* 2 *Author: Zhaofa Fang 3 *Created time: 2013-08-25-22.29 星期日 4 */ 5 #include <cstdio> 6 #include <cstdlib> 7 #include <sstream> 8 #include <iostream> 9 #include <cmath> 10 #include <cstring> 11 #include <algorithm> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 #include <queue> 16 #include <map> 17 #include <set> 18 using namespace std; 19 20 typedef long long ll; 21 typedef pair<int,int> PII; 22 #define DEBUG(x) cout<< #x << ':' << x << endl 23 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 24 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 25 #define REP(i,n) for(int i=0;i<(n);i++) 26 #define REPD(i,n) for(int i=(n-1);i>=0;i--) 27 #define PII pair<int,int> 28 #define PB push_back 29 #define ft first 30 #define sd second 31 #define lowbit(x) (x&(-x)) 32 #define INF (1<<30) 33 #define eps (1e-8) 34 35 const int maxq = 200011; 36 const int maxn = 30011; 37 int a[maxn],C[maxn],last[1000011]; 38 int ans[maxq]; 39 void init(){ 40 memset(C,0,sizeof(C)); 41 memset(last,-1,sizeof(last)); 42 } 43 struct Query{ 44 int l,r; 45 int idx; 46 bool operator < (const Query & rhs)const{ 47 return r < rhs.r; 48 } 49 }Q[maxq]; 50 51 void add(int x,int val){ 52 while(x<maxn){ 53 C[x] += val; 54 x += lowbit(x); 55 } 56 } 57 int sum(int x){ 58 int res = 0; 59 while(x > 0){ 60 res += C[x]; 61 x -= lowbit(x); 62 } 63 return res; 64 } 65 int main(){ 66 //freopen("in","r",stdin); 67 //freopen("out","w",stdout); 68 int n; 69 while(~scanf("%d",&n)){ 70 init(); 71 FOR(i,1,n)scanf("%d",&a[i]); 72 int q; 73 scanf("%d",&q); 74 REP(i,q){ 75 scanf("%d%d",&Q[i].l,&Q[i].r); 76 Q[i].idx = i; 77 } 78 sort(Q,Q+q); 79 int pre = 1; 80 REP(i,q){ 81 FOR(j,pre,Q[i].r){ 82 if(last[a[j]]==-1){ 83 add(j,1); 84 }else { 85 add(last[a[j]],-1); 86 add(j,1); 87 } 88 last[a[j]] = j; 89 } 90 ans[Q[i].idx] = sum(Q[i].r)-sum(Q[i].l-1); 91 pre = Q[i].r+1; 92 } 93 REP(i,q)printf("%d ",ans[i]); 94 } 95 return 0; 96 }