「LibreOJ#516」DP 一般看规律

首先对于序列上一点,它对答案的贡献只有与它的前驱和后驱(前提颜色相同)构成的点对,

于是想到用set维护每个颜色,修改操作就是将2个set暴力合并(小的向大的合并),每次插入时更新答案即可

颜色数要离散化,或者用map也行

Code

#include <cstdio>
#include <set>
#include <map>
#define N 100010
using namespace std;

int n,m,Ans=2147483647;
map<int,set<int>> A;

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

void upd(int c,int p){
	auto it=A[c].lower_bound(p);
	if(it!=A[c].end()) Ans=min(Ans,(*it)-p);
	if(it!=A[c].begin()) --it,Ans=min(Ans,p-(*it));
	A[c].insert(p);
}

int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i){int x=read();upd(x,i);}
	for(;m--;){
		int x=read(),y=read();
		if(x==y){printf("%d\n",Ans);continue;}//考虑特殊情况
		if(A[x].size()>A[y].size()) swap(A[x],A[y]);
		for(int it:A[x]) upd(y,it);
		A[x].clear();//合并后应清空
		printf("%d\n",Ans);
	}
	return 0;
}

 

posted @ 2018-07-17 20:14  void_f  阅读(227)  评论(0编辑  收藏  举报