莫队(不带修改)模板
给你一段序列,每次询问一段区间 问区间内存在多少个不同的数? 输入: n a[1],a[2].................a[n] m l1,r1 l2,r2 ..... ..... .... ln,rn 样例: 6 1 2 3 4 3 5 3 1 2 3 5 2 6 ---------- 2 2 4
代码:
重点:排序方式:(1)左端点所在的块 (2)右端点
先向外扩,再往里缩
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #define ll long long 6 #define inf 2147483600 7 using namespace std; 8 inline int read() 9 { 10 int x=0,w=1;char ch=getchar(); 11 while(!isdigit(ch)){if(ch=='-') w=-1;ch=getchar();} 12 while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); 13 return x*w; 14 } 15 const int N=50033; 16 int n,a[N],cnt[1000099]; 17 struct query{ 18 int l,r,id; 19 }q[200044]; 20 int bg[N],block,m,ans[200044]; 21 bool cmp(query x,query y) 22 { 23 if(bg[x.l]==bg[y.l]) return x.r<y.r; 24 else return bg[x.l]<bg[y.l]; 25 } 26 int l=1,r,tot; 27 int main() 28 { 29 n=read();block=sqrt(n); 30 for(int i=1;i<=n;++i) a[i]=read(),bg[i]=(i-1)/block+1; 31 m=read(); 32 for(int i=1;i<=m;++i) 33 q[i].l=read(),q[i].r=read(),q[i].id=i; 34 sort(q+1,q+m+1,cmp); 35 for(int i=1;i<=m;++i) 36 { 37 while(l<q[i].l) 38 { 39 cnt[a[l]]--; 40 if(cnt[a[l]]==0) tot--; 41 l++; 42 } 43 while(l>q[i].l) 44 { 45 l--; 46 if(cnt[a[l]]==0) tot++; 47 cnt[a[l]]++; 48 } 49 while(r<q[i].r) 50 { 51 r++; 52 if(cnt[a[r]]==0) tot++; 53 cnt[a[r]]++; 54 } 55 while(r>q[i].r) 56 { 57 cnt[a[r]]--; 58 if(cnt[a[r]]==0) tot--; 59 r--; 60 } 61 ans[q[i].id]=tot; 62 } 63 for(int i=1;i<=m;++i) 64 printf("%d\n",ans[i]); 65 return 0; 66 }