将所有x变为y 其实就是将x与y对应集合合并 最终经过n-1次合并后 集合数变为一个 所以在合并两个集合时 通过启发式合并 即总是将小集合并入大集合 这样最后复杂度是n*logn*logn
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=1e5+10;
struct node
{
int x,y;
};
set <int> st[3*maxn];
node order[maxn];
int ary[maxn],tmp[3*maxn],book[3*maxn];
int n,q,len;
int main()
{
set <int> ::iterator it,itt;
int i,ans,x,y,flag;
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++){
scanf("%d",&ary[i]);
tmp[i]=ary[i];
}
len=n;
for(i=1;i<=q;i++){
scanf("%d%d",&order[i].x,&order[i].y);
tmp[++len]=order[i].x,tmp[++len]=order[i].y;
}
sort(tmp+1,tmp+len+1);
len=unique(tmp+1,tmp+len+1)-tmp-1;
ans=2147483647;
for(i=1;i<=n;i++){
ary[i]=lower_bound(tmp+1,tmp+len+1,ary[i])-tmp;
it=st[ary[i]].upper_bound(i);
if(it!=st[ary[i]].end()){
ans=min(ans,*it-i);
}
if(it!=st[ary[i]].begin()){
it--;
ans=min(ans,i-*it);
}
st[ary[i]].insert(i);
}
for(i=1;i<=len;i++){
book[i]=i;
}
for(i=1;i<=q;i++){
x=lower_bound(tmp+1,tmp+len+1,order[i].x)-tmp;
y=lower_bound(tmp+1,tmp+len+1,order[i].y)-tmp;
if(x!=y){
if(st[book[x]].size()>st[book[y]].size()){
swap(book[x],book[y]);
}
for(itt=st[book[x]].begin();itt!=st[book[x]].end();itt++){
it=st[book[y]].upper_bound(*itt);
if(it!=st[book[y]].end()){
ans=min(ans,*it-*itt);
}
if(it!=st[book[y]].begin()&&st[book[y]].size()>0){
it--;
ans=min(ans,*itt-*it);
}
}
for(itt=st[book[x]].begin();itt!=st[book[x]].end();itt++){
st[book[y]].insert(*itt);
}
st[book[x]].clear();
}
printf("%d\n",ans);
}
return 0;
}