http://acm.hdu.edu.cn/showproblem.php?pid=1025
对p进行排序,然后就是对rich的最长上升子序列的求法,只是o(n^2)的算法不行,
要用d[i]表示序列长度为i时,最小的数为d[i],查找的时候用二分查找,查完的在把最小的放进去
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
using namespace std;
struct node
{
int rich;
int poor;
}num[500005];
bool operator <(node a,node b)
{
return a.poor<b.poor;
}
int ans[500005];
int d[500005];
int main()
{
int n;
int m=1;
while(scanf("%d",&n)==1)
{
for(int i=1;i<=n;i++)
scanf("%d%d",&num[i].poor,&num[i].rich);
sort(num+1,num+1+n);
fill(ans,ans+1+n,-1);
fill(d,d+n+1,-1);
d[1]=num[1].rich;
for(int i=2;i<=n;i++)
{
int left=1;
int right=i;
while(left<right)
{
int mid=(left+right)/2;
if(d[mid]!=-1&&d[mid]<num[i].rich)
{
left=mid+1;
}
else
{
right=mid;
}
}
if(d[left]<num[i].rich)
{
if(d[left]!=-1)
d[left]=min(d[left],num[i].rich);
else
d[left]=num[i].rich;
}
else
d[left]=min(d[left],num[i].rich);
}
int ans;
for(int i=n;i>=1;i--)
if(d[i]!=-1)
{
ans=i;
break;
}
if(ans==1)
printf("Case %d:\nMy king, at most %d road can be built.\n\n",m++,ans);
else
printf("Case %d:\nMy king, at most %d roads can be built.\n\n",m++,ans);
}
}