「LibreOJ β Round #2」DP 一般看规律 LOJ - 516

https://loj.ac/problem/516

将所有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;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/88075291
今日推荐