2020牛客寒假算法基础集训营6 C题

汉诺塔

题目描述

现在你有 N 块矩形木板,第 i 块木板的尺寸是 Xi*Yi,你想用这些木板来玩汉诺塔的游戏。
我们知道玩汉诺塔游戏需要把若干木板按照上小下大的顺序堆叠在一起,但因为木板是矩形,所以有一个问题:
第 i 块木板能放在第 j 块木板上方当且仅当 Xi 你想把这些木板分为尽可能少的组,使得每组内的木板都能按照一定的次序叠放。
你需要给出任意一种合理的分组方案。
提醒:“任意”意味着你的答案不必和标准输出完全一致,只要正确即可。

输入描述:

第一行,一个正整数 N
接下来 N 行,每行两个正整数表示 Xi 和 Yi
对于所有的数据,1≤N≤100,000,1≤Xi,Yi≤N,Xi 互不相等且 Yi 互不相等

输出描述:

输出文件包含两行,第一行一个正整数,表示最少组数
第二行 N 个正整数,依次表示你的方案中每块木板分在了哪一组
组的编号必须是从 1 开始的连续整数


这道题用到了,Dilworth定理

其实知道了这个定理,这道题就会做了,还有个技巧是二分在求得最长递减子序列的长度时,把分组一起算了出来,当一个元素可以被另一个元素在其位置取代时,这些元素就被分在了同一个组;

代码:

#include
#define ll long long
#define pa pair
#define lson k<<1
#define rson k<<1|1
#define inf 0x3f3f3f3f
//ios::sync_with_stdio(false);
using namespace std;
const int N=100100;
const int M=1000100;
const ll mod=998244353;
struct Node{
	int x,y;
	int post;
}a[N];
bool cmp(Node p,Node q){
	return p.x<q.x;
}
int ans[N];
int sta[N];
int main(){
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].x>>a[i].y;
		a[i].post=i;
	} 
	sort(a+1,a+1+n,cmp);
	int m=0;
	for(int i=1;i<=n;i++){
		int l=1,r=m;
		while(l<=r){
			int d=(l+r)>>1;
			if(sta[d]<a[i].y) r=d-1;
			else l=d+1;
		}
		sta[l]=a[i].y;
		if(l>m) m=l;
		ans[a[i].post]=l;
	}
	cout<<m<<endl;
	for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
	return 0;
}

你可能感兴趣的:(#,单调栈,LIS)