维护一个区间内不同数的个数,最直观的想法是直接排序后用树状数组维护即可。但是我们发现n只有3e4,于是我们想到了可以拿一个$O(n\sqrt{n})$的莫队维护。关于莫队算法如果有不知道的或者不会写的,建议看一看这位大佬的博客
1 #pragma GCC optimize(3) 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #define N 1000005 8 using namespace std; 9 inline int read() 10 { 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} 14 return x*f; 15 } 16 inline void write(int x) 17 { 18 if(x>9)write(x/10); 19 putchar(x%10+'0'); 20 } 21 struct query 22 { 23 int l,r,x; 24 }qry[N]; 25 int n,m,a[N],cnt[N],belong[N],siz,bnum,l=1,r=0,now,ans[N]; 26 bool cmp(query a,query b) 27 { 28 return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.l]&1)?a.r<b.r:a.r>b.r); 29 } 30 int main() 31 { 32 n=read(); 33 for(int i=1;i<=n;i++)a[i]=read(); 34 siz=sqrt(n);bnum=ceil((double)(n/siz)); 35 for(int i=1;i<=bnum;i++) 36 { 37 for(int j=(i-1)*siz+1;j<=i*siz;j++) 38 { 39 belong[j]=i; 40 } 41 } 42 m=read(); 43 for(int i=1;i<=m;i++)qry[i].l=read(),qry[i].r=read(),qry[i].x=i; 44 sort(qry+1,qry+1+m,cmp); 45 for(int i=1;i<=m;i++) 46 { 47 int ll=qry[i].l,rr=qry[i].r; 48 while(l<ll)now-=!(--cnt[a[l++]]); 49 while(l>ll)now+=!(cnt[a[--l]]++); 50 while(r<rr)now+=!(cnt[a[++r]]++); 51 while(r>rr)now-=!(--cnt[a[r--]]); 52 ans[qry[i].x]=now; 53 } 54 for(int i=1;i<=m;i++)write(ans[i]),puts(""); 55 return 0; 56 }