模板代码HH的项链
学习笔记
时间复杂度 时间复杂度2 带修改莫队复杂度
1 #include <iostream>
2 #include <cstdio>
3 #include <cmath>
4 #include <algorithm>
5 #define reg register
6 using namespace std;
7 const int MN=50005,NM=200005;
8 int h[MN],n,q,a[MN],ans[NM];
9 struct data{
10 int l,r,id;
11 bool operator<(const data&b)const{
12 if (h[l]==h[b.l]) return r<b.r;//如果左端点在同一块,按右端点排序
13 return l<b.l;//否则按左端点排序
14 }
15 }que[NM];
16 inline int ri(){
17 char c=getchar();int x=0,w=1;
18 while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
19 while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();}
20 return x*w;
21 }
22 inline void blocker(){
23 int k=sqrt(n);
24 for(reg int i=1;i<=n;i++)h[i]=(i-1)/k+1;//分出根号n个块
25 }
26 int L,R,now,hsh[1000005];
27 inline void move(int x,int d){
28 if (d==1){
29 if(hsh[a[x]]==0)now++; hsh[a[x]]++;
30 }
31 else{
32 hsh[a[x]]--; if(hsh[a[x]]==0)now--;
33 }
34 }
35 int main(){
36 n=ri();
37 for(reg int i=1;i<=n;i++)a[i]=ri();
38 blocker(),q=ri();
39 for(reg int i=1;i<=q;i++) que[i].l=ri(),que[i].r=ri(),que[i].id=i;
40 sort(que+1,que+1+q);
41 for(reg int i=1;i<=q;i++){
42 while (L<que[i].l) move(L++,-1);//缩小
43 while (L>que[i].l) move(--L,1);//扩大
44 while (R<que[i].r) move(++R,1);//扩大
45 while (R>que[i].r) move(R--,-1);//缩小
46 ans[que[i].id]=now;
47 }
48 for(reg int i=1;i<=q;i++) printf("%d\n",ans[i]);
49 return 0;
50 }