洛谷 P3901 数列找不同
题目描述
现有数列 A1,A2,⋯,AN ,Q 个询问 (Li,Ri) , ALi,ALi+1,⋯,ARi 是否互不相同
输入格式:
第1 行,2 个整数 N,Q
第2 行,N 个整数 ALi,ALi+1,⋯,ARi
Q 行,每行2 个整数 Li,Ri
输出格式:
对每个询问输出一行,“Yes” 或者“No”
说明
• 对于50% 的数据, N,Q≤103
• 对于100% 的数据, 1≤N,Q≤105,1≤Ai≤N,1≤Li≤Ri≤N
题解:
此题为水题一枚,暴力+预处理直接过,做作的我用了莫队~V~
其实一看就是莫队模板题,只不过要一个小小的转化思考。
判断一段数是否互不相同其实就只要记录下这一段内不同数的个数 sum,如果 sum== r-l+1 那么就说明这一段数是互不相同的。
废话不多说,上代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100005; 4 int n,m,a[N],block,belong[N],sum,num[N]; 5 string ans[N]; 6 struct node{ 7 int l,r,id; 8 }q[N]; 9 inline int read() 10 { 11 int x=0,f=1; char ch=getchar(); 12 while (!isdigit(ch)) 13 f=(ch=='-')?-f:f,ch=getchar(); 14 while (isdigit(ch)) 15 x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); 16 return x*f; 17 } 18 bool cmp(node a,node b) 19 { 20 return belong[a.l]==belong[b.l]?(belong[a.r]==belong[b.r]?a.id<b.id:a.r<b.r):a.l<b.l; 21 } 22 void revise(int x,int w) 23 { 24 num[a[x]]+=w; 25 if (w>0) sum+=(num[a[x]]==1); 26 if (w<0) sum-=(num[a[x]]==0); 27 } 28 int main() 29 { 30 n=read(),m=read(); block=sqrt(n); 31 for (int i=1; i<=n; i++) 32 { 33 a[i]=read(); belong[i]=i/block+1; 34 } 35 for (int i=1; i<=m; i++) 36 { 37 q[i].l=read(),q[i].r=read(),q[i].id=i; 38 } 39 sort(q+1,q+1+m,cmp); 40 int zl=1,zr=0; sum=0; 41 memset(num,0,sizeof(num)); 42 for (int i=1; i<=m; i++) 43 { 44 while (zl<q[i].l) revise(zl,-1),zl++; 45 while (zl>q[i].l) revise(zl-1,1),zl--; 46 while (zr<q[i].r) revise(zr+1,1),zr++; 47 while (zr>q[i].r) revise(zr,-1),zr--; 48 if (sum==zr-zl+1) ans[q[i].id]="Yes"; 49 else ans[q[i].id]="No"; 50 } 51 for (int i=1; i<=m; i++) 52 cout<<ans[i]<<endl; 53 return 0; 54 }
加油加油加油!!! fighting fighting fighting !!!