Codeforces - Closest Equals

題目鏈接:Codeforces - Closest Equals


顯然可以離線。

然後對每一個詢問,我們按照右端點排序,之後只考慮左端點就行了,所以我們對每一對滿足的,我們就修改左邊的哪個值即可。

然後就變成了區間min,線段樹即可。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5e5+10;
int n,m,a[N],res[N],mi[N<<2];	map<int,int> mp;
struct node{int l,r,id;}t[N];
#define mid (l+r>>1)
void build(int p,int l,int r){
	if(l==r){mi[p]=1e9;	return ;}
	build(p<<1,l,mid),build(p<<1|1,mid+1,r);
	mi[p]=min(mi[p<<1],mi[p<<1|1]);
}
void change(int p,int l,int r,int x,int v){
	if(l==r){mi[p]=min(mi[p],v); return ;}
	if(x<=mid)	change(p<<1,l,mid,x,v);
	else change(p<<1|1,mid+1,r,x,v);
	mi[p]=min(mi[p<<1],mi[p<<1|1]);
}
int ask(int p,int l,int r,int ql,int qr){
	if(l==ql&&r==qr)	return mi[p];
	if(qr<=mid)	return ask(p<<1,l,mid,ql,qr);
	else if(ql>mid)	return ask(p<<1|1,mid+1,r,ql,qr);
	else return min(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)	scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)	scanf("%d %d",&t[i].l,&t[i].r),t[i].id=i;
	sort(t+1,t+1+m,[](node a,node b){
		return a.r<b.r;
	});
	int pos=1;	build(1,1,n);
	for(int i=1;i<=m;i++){
		while(pos<=t[i].r){
			if(mp[a[pos]])	change(1,1,n,mp[a[pos]],pos-mp[a[pos]]);
			mp[a[pos]]=pos;	pos++;
		}
		res[t[i].id]=ask(1,1,n,t[i].l,t[i].r);
	}
	for(int i=1;i<=m;i++)
		if(res[i]==1e9)	puts("-1");
		else	printf("%d\n",res[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章