一、算法分析
代码里面讲的已经比较详细了,这道题涉及LIS类的问题,而且涉及到dilworth定理。
二、代码及注释
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n;
struct stk{
int l;
int w;
stk(int lp,int wp):l(lp),w(wp){}
};
bool cmp(stk x,stk y){
return x.l>y.l;
}
vector<stk> a;
vector<int> b,c;
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
cin>>n;
int lp,wp;
for(int i=0;i<n;i++){
cin>>lp>>wp;
a.push_back(stk(lp,wp));
}
sort(a.begin(),a.end(),cmp); //处理这种嵌套矩形类问题,因为有两个参数,通常我们确定其中一个,然后处理另外一个。此处就是先把长度排好序,再处理宽度的最长不上升子序列
for(int i=0;i<n;i++){ //这样的问题显然就要对木棍的宽度进行遍历
b.push_back(a[i].w); //c的最后一个元素是我们假设的不下降子序列的结束点(会持续更新),不上升子序列的最小划分等于最长上升子序列的长度,所以这里求的是最长上升的子序列长度
}
c.push_back(b[0]);
for(int i=0;i<n;i++){ //接下来就是一个最长上升子序列的模板了
if(b[i]>c.back()) c.push_back(b[i]); //如果有比结束点大的,就加进序列里面
//否则就通过二分查找,更正前面的序列
else{
int l=0,r=c.size()-1;
while(l<r){
int mid=(l+r)/2;
if(c[mid]>=b[i]){ //这样的二分查找,不一定会找到一个准确的值等于b[i],但是会找到一个尽量接近b[i]的值
r=mid;
}
else{
l=mid+1;
}
}
//cout<<"??"<<c[l]<<' '<<b[i]<<endl; //这里可以输出一下中间变量作为测试
c[l]=b[i];
}
}
cout<<c.size();
return 0;
}
注明:解题思路参考了洛谷该题的题解的第一篇即用户名为dreagonm写的题解,参考了其中部分思想,在此注明并表示感谢。
参考文献