【題解】Luogu P3901 數列找不同
阿新 • • 發佈:2018-11-16
原題傳送門
不錯的莫隊練手題
塊數就直接取sqrt(n)
對所有詢問進行排序
排序第一關鍵詞:l所在第幾塊,第二關鍵詞:r的位置
考慮Ai不大,暴力開陣列
add時如果加之後的數量是1
總數就加1
del時如果減之後的數量是0
總數就減1
每次比較總數和該次查詢區間的長度
相等的話就把 ans[q[i].id]設為真
最後如果ans[i]為真就輸出Yes,否則輸出No
#pragma GCC optimize("O3") #include <bits/stdc++.h> #define N 100005 using namespace std; inline int read() { register int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f; } int v[N],blocksize=0; struct query{ int l,r,id,bl; }q[N]; int sum[N]; bool ans[N]; int cnt=0; inline void add(register int x) { if(++sum[v[x]]==1) ++cnt; } inline void del(register int x) { if(--sum[v[x]]==0) --cnt; } inline bool cmp(register query a,register query b) { return a.bl==b.bl?a.r<b.r:a.bl<b.bl; } int main() { memset(sum,0,sizeof(sum)); int n=read(),m=read(); blocksize=sqrt(n); for(register int i=1;i<=n;++i) v[i]=read(); for(register int i=1;i<=m;++i) { int l=read(),r=read(); q[i]=(query){l,r,i,(l-1)/blocksize+1}; } sort(q+1,q+m+1,cmp); int l=1,r=0; for(register int i=1;i<=m;++i) { int ll=q[i].l,rr=q[i].r; while(l<ll) del(l++); while(l>ll) add(--l); while(r<rr) add(++r); while(r>rr) del(r--); ans[q[i].id]=(cnt==rr-ll+1)?1:0; } for(register int i=1;i<=m;++i) if(ans[i]) puts("Yes"); else puts("No"); return 0; }