2018.10.20【校内模拟】蛋糕(LIS/Dilworth)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83215267

传送门


解析:

按照第一位 a a 排序从大到小,求 b b 的最少的下降序列的划分数。

转换一下,求 b b 的最少下降序列个数。

根据 D i l w o r t h Dilworth 定理,由于没有相等,我们要求的就是 b b 的最长上升子序列的长度。

对于输出方案,我们在每个上升序列的位置维护一个 h e a d head ,能够补到这个位置的数就能够在最后的下降序列中出现在以 h e a d head 开头的序列中。并查集维护一下就好了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

inline void outint(int a){
	static char ch[13];
	if(a==0)return (void)pc('0');
	while(a)ch[++ch[0]]=a-a/10*10,a/=10;
	while(ch[0])pc(ch[ch[0]--]^48);
}

cs int N=1000006;

int fa[N];
inline int getfa(int x){
	while(x^fa[x])x=fa[x]=fa[fa[x]];
	return x;
}
inline void merge(int u,int v){
	u=getfa(u);
	v=getfa(v);
	fa[max(u,v)]=min(u,v);
}
int pos[N],tot;

int len;
int a[N],head[N];
int b[N];
int id[N];
int n;
signed main(){
	n=getint();
	for(int re i=1;i<=n;++i){
		int x=getint(),
		y=getint();
		b[x]=y;
		id[x]=i;
		fa[i]=i;
	}
	for(int re i=n;i;--i){
		int c=b[i];
		if(len==0||c>a[len]){
			a[++len]=c;
			head[len]=id[i];
		}
		else{
			int k=lower_bound(a+1,a+len+1,c)-a;
			merge(head[k],id[i]);
			a[k]=c;
		}
	}
	cout<<len<<"\n";
	for(int re i=1;i<=n;++i)if(fa[i]==i)pos[i]=++tot;
	for(int re i=1;i<=n;++i)outint(pos[getfa(i)]),pc(' ');
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/83215267