DP 一般看規律

題目鏈接:DP 一般看規律


顯然我們可以發現答案是不會變大的。

所以我們可以一直維護當前的最小值。

每次做顏色合併的時候,就可以直接利用set啓發式合併。

然後並且維護答案。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=3e5+10;
int n,m,a[N],x[N],y[N],id[N],sz,res=2147483647;
set<int> s[N];	vector<int> v;
inline int get(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
inline void merge(int s1,int s2){
	if(s1==s2)	return ; int flag=0;
	if(s[s2].size()<s[s1].size()) swap(s1,s2),flag=1;
	for(auto i=s[s1].begin();i!=s[s1].end();i++){
		auto lst=s[s2].lower_bound(*i);
		if(lst!=s[s2].end())	res=min(res,*lst-*i);
		auto pre=s[s2].lower_bound(*i);
		if(pre!=s[s2].begin())	pre--,res=min(res,*i-*pre);
	}
	for(auto i=s[s1].begin();i!=s[s1].end();i++)	s[s2].insert(*i);
	s[s1].clear(); if(flag) swap(s[s1],s[s2]);
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)	scanf("%d",&a[i]),v.push_back(a[i]);
	for(int i=1;i<=m;i++)	
		scanf("%d %d",&x[i],&y[i]),v.push_back(x[i]),v.push_back(y[i]);
	sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end()); sz=v.size();
	for(int i=1;i<=sz;i++)	id[i]=i;
	for(int i=1;i<=n;i++)	a[i]=get(a[i]),s[a[i]].insert(i);
	for(int i=1;i<=sz;i++)	if(s[i].size()>1){
		for(auto j=++s[i].begin(),k=s[i].begin();j!=s[i].end();j++,k++)	res=min(res,*j-*k);
	}
	for(int i=1;i<=m;i++){
		x[i]=get(x[i]),y[i]=get(y[i]);	merge(x[i],y[i]);
		printf("%d\n",res);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章