[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 }
View Code

 

posted @ 2017-01-02 11:21  KingSann  阅读(118)  评论(0编辑  收藏  举报