https://vjudge.net/problem/POJ-1065
给定你一些木材,每次进行加工的时候
x1,y1 x2,y2
如果满足 x1<=x2&&y1<=y2 ,那么就不用重开
否则就得重开,重开一次费一秒,问你最少的花费是多少。
根据 偏序集定理, 把 x升序排之后
求他的 y的最长严格递减子序列就行。。
http://blog.csdn.net/acdreamers/article/details/7626671
acmdreaer的证明。
自己的二分的老错qwq
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
/*acdreamer神的 导弹拦截问题。
根据
第一题 不严格下降- 严格上升。
所以这道题是 求 不严格上升-严格下降。
由定理可得,求一个二维的最长严格上升序列
模拟
*/
using namespace std;
const int maxn=6000;
struct Node
{ int x;
int y;
}node[maxn];
bool cmp2(Node a,Node b){
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
int m;
vector<int>q;
int solve(int x){
int r=q.size()-1;
int l=0;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(q[mid]>x){
ans=mid;
l=mid+1;
return ans;
}
else r=mid-1;
}
return ans;
}
int main()
{ int t,sum;
scanf("%d",&t);
while(t--){
scanf("%d",&m);
sum=0;
for(int i=0;i<m;i++)
scanf("%d%d",&node[i].y,&node[i].x);
sort(node,node+m,cmp2);
for(int i=0;i<m;i++)
node[i].y=-node[i].y;
// skill-one:
vector<int>q;
for(int i=0;i<m;i++){
int u=lower_bound(q.begin(),q.end(),node[i].y)-q.begin();
if(u==q.size())
q.push_back(node[i].y);
else
q[u]=node[i].y;
}
printf("%d\n",q.size());
//手写二分,锻炼身体,还能长脑子
/* q.clear();
for(int i=0;i<m;i++){
int u=solve(node[i].y); //自己写的二分老是错。。我也是不知道为啥了
if(u==-1){
q.push_back(node[i].y);
}
else
q[u]=node[i].y;
}
for(int i=0;i<q.size();i++)
cout<<q[i]<<endl;
printf("%d\n",q.size());*/
}
return 0;
}