漢諾塔
題目描述
現在你有 N 塊矩形木板,第 i 塊木板的尺寸是 Xi*Yi,你想用這些木板來玩漢諾塔的遊戲。
我們知道玩漢諾塔遊戲需要把若干木板按照上小下大的順序堆疊在一起,但因爲木板是矩形,所以有一個問題:
第 i 塊木板能放在第 j 塊木板上方當且僅當 Xi<Xj 且 Yi<Yj,於是你很可能沒法把所有的木板按照一定的次序疊放起來。
你想把這些木板分爲儘可能少的組,使得每組內的木板都能按照一定的次序疊放。
你需要給出任意一種合理的分組方案。
提醒:“任意”意味着你的答案不必和標準輸出完全一致,只要正確即可。
輸入描述:
第一行,一個正整數 N
接下來 N 行,每行兩個正整數表示 Xi 和 Yi
對於所有的數據,1≤N≤100,000,1≤Xi,Yi≤N,Xi 互不相等且 Yi 互不相等
輸出描述:
輸出文件包含兩行,第一行一個正整數,表示最少組數
第二行 N 個正整數,依次表示你的方案中每塊木板分在了哪一組
組的編號必須是從 1 開始的連續整數
這道題用到了,Dilworth定理
其實知道了這個定理,這道題就會做了,還有個技巧是二分在求得最長遞減子序列的長度時,把分組一起算了出來,當一個元素可以被另一個元素在其位置取代時,這些元素就被分在了同一個組;
代碼:
#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
#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;
}