題目鏈接: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;
}