牛客 - 汉诺塔(思维+dp)

题目链接:点击查看

题目大意:给出 n 个木板,尺寸分别为 Xi * Yi ,现在要求将其分为最少的组,每一个组中都可以通过重新排序使得每个木板都严格递增,此处递增的意思为严格满足 Xi > Xj && Yi > Yj

题目分析:借这个题学到了一个很牛的Dilworth定理,百度百科的内容非常不友善,稍微简单的说一下就是,对于一个数列来说,其最长不下降子序列的个数等于其最长不上升子序列的长度,反过来也一样,所以这个题对于X或者Y任意一维排完序后,求一下最长不下降子序列就是答案了,因为题目还要求输出一下分组,在状态转移的时候顺便储存一下就好了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;
    
typedef long long LL;
   
typedef unsigned long long ull;
    
const int inf=0x3f3f3f3f;
    
const int N=1e5+100;

struct Node
{
	int x,y,id;
	bool operator<(const Node& a)const
	{
		return x<a.x;
	}
}a[N];

int d[N],ans[N],len;

int main()
{
//#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
//#endif
//  ios::sync_with_stdio(false);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].x,&a[i].y);
		a[i].id=i;
	}
	sort(a+1,a+1+n);
	len=1;
	d[len]=a[1].y;
	ans[a[1].id]=len;
	for(int i=2;i<=n;i++)
	{
		if(a[i].y<d[len])
		{
			d[++len]=a[i].y;
			ans[a[i].id]=len;
		}
		else
		{
			int j=upper_bound(d+1,d+1+len,a[i].y,greater<int>())-d;
			d[j]=a[i].y;
			ans[a[i].id]=j;
		}
	}
	printf("%d\n",len);
	for(int i=1;i<=n;i++)
		printf("%d ",ans[i]);
	
    		
     
     
     
     
     
       
       
       
       
       
       
       
    return 0;
}
发布了646 篇原创文章 · 获赞 20 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104337907