洛谷 P3901 数列找不同
这道题与HH的项链几乎一模一样,好吧根本就是一样的
思路:我们考虑统计区间内有多少互不相同的数,然后与区间长度比较
进一步思考:
考虑把区间分类,按照右端点分为n类,然后考虑怎么快速算每一类的答案
当我们考虑到第r类区间时,我们仅考虑前r个数
由于区间的右端点均为r,所以所有的区间都是后缀,靠后的数对所有区间的影响更大
所以如果有两个相同的数,设位置为p1,p2(p1<p2),我们更愿意保留后一个数,这样
我们在新的数组A中a[p2]++
这样所有一个区间内互不相同的数的数量,就是A数组对应区间内元素和
A数组可以用树状数组维护
每次不断r++,把新数加入,更新树状数组,相同的就取后一个
[Code]
#include <bits/stdc++.h>
using namespace std;
int read(){
int x=0,flag=1; char c;
for(c=getchar();!isdigit(c);c=getchar()) if(c=='-') flag=-1;
for(;isdigit(c);c=getchar()) x=((x+(x<<2))<<1)+(c^48);
return x*flag;
}
const int N=1e5+50;
int n,m;
int a[N];
struct opt{//询问
int l,r;
int id;
}b[N];
bool cmp(opt x,opt y){
return x.r<y.r;
}
int c[N];//树状数组
int lowbit(int x) { return x&(-x); }
int query(int x){
int ret=0;
for(int i=x;i>0;i-=lowbit(i)) ret+=c[i];
return ret;
}
void update(int x,int y){
for(int i=x;i<=n;i+=lowbit(i)) c[i]+=y;
}
int p[N];//每个数前一个跟它相同的数的位置,初始为-1
int ans[N];
int main() {
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++){
b[i].l=read(),b[i].r=read();
b[i].id=i;
}
sort(b+1,b+m+1,cmp);//询问排序
memset(p,-1,sizeof(p));
int r=0;
for(int i=1;i<=m;i++){
while(r<b[i].r){
++r;
if(p[a[r]]!=-1) update(p[a[r]],-1);
update(r,1); p[a[r]]=r;
}
int sum=query(b[i].r)-query(b[i].l-1);
if(sum==b[i].r-b[i].l+1) ans[b[i].id]=1;
}
for(int i=1;i<=m;i++)
puts(ans[i]?"Yes":"No");
return 0;
}