[bzoj1878]HH的项链
吼吼吼吼吼A掉的第一道莫队算法的题。。
没什么难度。。开个cnt数组统计一下当前区间里各个数字的出现次数,然后addition、remove函数中适时维护当前的ans变量。。
(当然也可以开个last、next数组维护一下前一个相同元素和后一个相同元素的位置然后乱搞,当然貌似空间有些衰了。。)
(等等用char来记cnt的话会炸?!呀赶紧改一下代码去。。。)
一定不要忘了写分块!一定不要忘了写分块!一定不要忘了写分块!

1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdlib> 5 #include <map> 6 #include <string> 7 #include <vector> 8 #include <stack> 9 #include <cmath> 10 #include <queue> 11 #include <cstdio> 12 #include <set> 13 using namespace std; 14 15 int cnt[1000100]; 16 int n,m,a[210000],l,r,ans; 17 struct B{ 18 int l,r,id,ans,b; 19 bool operator < (B a) const { 20 return b==a.b?r<a.r:b<a.b; 21 } 22 }b[210000]; 23 void add(int i){ 24 cnt[a[i]]++; 25 if(cnt[a[i]]==1)ans++; 26 } 27 void rem(int i){ 28 cnt[a[i]]--; 29 if(cnt[a[i]]==0)ans--; 30 } 31 bool cmp(B a,B b){return a.id<b.id;} 32 int main(){ 33 scanf("%d",&n); 34 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 35 int len=sqrt(n); 36 scanf("%d",&m); 37 for(int i=1;i<=m;i++){ 38 scanf("%d%d",&b[i].l,&b[i].r); 39 b[i].id=i; 40 b[i].b=b[i].l/len; 41 } 42 sort(b+1,b+1+m); 43 l=b[1].l,r=b[1].r; 44 for(int i=l;i<=r;i++)add(i); 45 for(int i=1;i<=m;i++){ 46 while(r<b[i].r)add(++r); 47 while(r>b[i].r)rem(r--); 48 while(l<b[i].l)rem(l++); 49 while(l>b[i].l)add(--l); 50 b[i].ans=ans; 51 } 52 sort(b+1,b+1+m,cmp); 53 for(int i=1;i<=m;i++)printf("%d\n",b[i].ans); 54 }