数列找不同
题目描述
现有数列 A 1 , A 2 , … , A N A_1,A_2,\ldots,A_N A1,A2,…,AN, Q Q Q 个询问 ( L i , R i ) (L_i,R_i) (Li,Ri),询问 A L i , A L i + 1 , … , A R i A_{L_i} ,A_{L_i+1},\ldots,A_{R_i} ALi,ALi+1,…,ARi 是否互不相同。
输入格式
第一行,两个整数
N
,
Q
N,Q
N,Q。
第二行,
N
N
N 个整数
A
1
,
A
2
,
…
,
A
N
A_1, A_2, \ldots , A_N
A1,A2,…,AN。
接下来
Q
Q
Q 行,每行两个整数
L
i
,
R
i
L_i,R_i
Li,Ri。
输出格式
对每个询问输出一行,Yes
或 No
。
样例 #1
样例输入 #1
4 2
1 2 3 2
1 3
2 4
样例输出 #1
Yes
No
提示
对于
50
%
50\%
50% 的数据,
N
,
Q
≤
1
0
3
N,Q \le 10^3
N,Q≤103。
对于
100
%
100\%
100% 的数据,
1
≤
N
,
Q
≤
1
0
5
1 \le N,Q \le 10^5
1≤N,Q≤105,
1
≤
A
i
≤
N
1 \le A_i \le N
1≤Ai≤N,
1
≤
L
i
≤
R
i
≤
N
1 \le L_i \le R_i \le N
1≤Li≤Ri≤N。
代码
//基础莫队
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N = 1e5+10;
int w[N];
struct E{
int id,l,r;
}q[N];
int n,m;
int res,cnt[N];
int len;
int ans[N];
int get(int x){
return x/len;
}
bool cmp(const E&a,const E&b){
int i=get(a.l),j=get(b.l);
if(i!=j)return i<j;
return a.r<b.r;
}
void add(int x,int& res){
if(!cnt[x])res++;
cnt[x]++;
}
void del(int x,int& res){
cnt[x]--;
if(!cnt[x])res--;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>w[i];
}
for(int i=1;i<=m;i++){
int l,r;
cin>>l>>r;
q[i]={i,l,r};
}
len=sqrt(n);
sort(q+1,q+1+m,cmp);
//i是右端点,j是左端点
for(int k=1,i=0,j=1,res=0;k<=m;k++){
int id=q[k].id,l=q[k].l,r=q[k].r;
while(i<r)add(w[++i],res);
while(i>r)del(w[i--],res);
while(j<l)del(w[j++],res);
while(j>l)add(w[--j],res);
if(res==(r-l+1)){
ans[id]=1;
}
}
for(int i=1;i<=m;i++){
// cout<<ans[i]<<endl;
if(ans[i]==1){
puts("Yes");
}else{
puts("No");
}
}
return 0;
}