[SP3267]DQUERY - D query

题目传送门

维护一个区间内不同数的个数,最直观的想法是直接排序后用树状数组维护即可。但是我们发现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 }
View Code

猜你喜欢

转载自www.cnblogs.com/szmssf/p/11546187.html