https://ac.nowcoder.com/acm/contest/3007/C
将木板按照Xi从小到大排序,将这时的Yi数列记为Zi数列,则问题变成将Zi划分为尽可能少的若干组上升子序列。
根据Dilworth定理,最小组数等于Zi的最长下降子序列长度。
要求最长下降子序列的长度,我们有一种经典的二分优化dp的方法,在这里不再详述。 借助这种做法我们能给出一种构造方法,在求出最小组数的同时得出方案。
将状态数组的每个位置变为栈,用入栈操作代替修改元素操作,即可在求出组数的同时,用这些栈来完成对数列的划分。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e5+5; 4 struct node{ 5 int x,y; 6 int indx; 7 bool operator < (const node & b) const{ 8 return x < b.x; 9 } 10 }g[maxn]; 11 int dp[maxn],group[maxn]; 12 int main(){ 13 int n;cin>>n; 14 for(int i = 1;i<=n;i++) { 15 cin>>g[i].x>>g[i].y; 16 g[i].indx = i; 17 } 18 sort(g+1,g+1+n); 19 int siz = 0; 20 for(int i = 1;i<=n;i++){ 21 int l = 1,r = siz; 22 while(l<=r){//用二分进行优化时间复杂度 23 int mid = (l+r)/2; 24 if(dp[mid]<g[i].y) r = mid - 1; 25 else l = mid + 1; 26 } 27 dp[l] = g[i].y; 28 if(l > siz) siz = l; 29 group[g[i].indx] = l; 30 } 31 cout<<siz<<endl; 32 for(int i = 1;i<=n;i++){ 33 cout<<group[i]<<" "; 34 } 35 return 0; 36 }