洛谷 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;
}


原文地址:https://www.cnblogs.com/zzhzzh123/p/12221689.html