题目描述
现有数列A_1,A_2,cdots,A_NA1,A2,⋯,AN,Q 个询问(L_i,R_i)(Li,Ri),A_{Li} ,A_{Li+1},cdots,A_{Ri}ALi,ALi+1,⋯,ARi 是否互不相同
输入格式
第1 行,2 个整数N,QN,Q
第2 行,N 个整数A_{Li} ,A_{Li+1},cdots,A_{Ri}ALi,ALi+1,⋯,ARi
Q 行,每行2 个整数L_i,R_iLi,Ri
输出格式
对每个询问输出一行,“Yes” 或者“No”
输入输出样例
输入 #1
4 2 1 2 3 2 1 3 2 4
输出 #1
Yes No
说明/提示
• 对于50% 的数据,N,Q le 10^3N,Q≤103
• 对于100% 的数据,1 le N,Q le 10^5, 1 le A_i le N, 1 le L_i le R_i le N1≤N,Q≤105,1≤Ai≤N,1≤Li≤Ri≤N
我们想,因为每次查询是离线的,所以我们先给每次的查询排一个序。
排序的方法是
分块。
我们把所有的元素分成多个块(即分块)。分了块跑的会更快。再按照右端点从小到大,左端点块编号相同按右端点从小到大。
#include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int maxn=100010; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-'){ w=-1; } ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } int n,m,hhh,ans=0,kkksc03,kkksc04,cnt[maxn],a[maxn],i; bool anb[maxn]; struct node{ int l,r,p; }q[maxn]; bool cmp(const node x,const node y){ return (x.l/hhh)==(y.l/hhh)?x.r<y.r:x.l<y.l; } void add(int position){ if((++cnt[a[position]])==1){ ++ans; } } void remove(int position){ if((--cnt[a[position]])==0){ --ans; } } int main(){ n=read(); m=read(); hhh=sqrt(n); for(i=1;i<=n;i++){ a[i]=read(); } for(i=1;i<=m;i++){ q[i].l=read(); q[i].r=read(); q[i].p=i; } sort(q+1,q+1+m,cmp); for(i=1;i<=m;i++){ int L=q[i].l,R=q[i].r; while(kkksc03<L){ remove(kkksc03++); } while(kkksc03>L){ add(--kkksc03); } while(kkksc04<R){ add(++kkksc04); } while(kkksc04>R){ remove(kkksc04--); } if(ans==(R-L+1)){ anb[q[i].p]=1; } } for(i=1;i<=m;i++){ if(anb[i]==1){ printf("Yes "); } else{ printf("No "); } } return 0; }