题目链接:点击查看
题目大意:给出 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;
}