因为题目给出不能交叉,一条边的两个点一个看做下标,一个看做值,那么就是 i>=j,then a[i] >=a[j] ,所以满足上升不降子序列,求建路条数最多,其实就是最长上升子序列
ac代码如下:
采用的是nlogn的二分法模板求取最长上升子序列模板及讲解链接
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 500007
using namespace std;
int n;
struct Road
{
int r,p;
bool operator < ( const Road & a ) const
{
if ( r == a.r ) return p < a.p;
return r < a.r;
}
}r[MAX];
int dp[MAX];
int d[MAX];
int get ( int n )
{
int left = 0 , right = n-1 , mid;
while ( left != right )
{
mid = (left + right+1) >> 1;
if ( r[n].p >= d[mid] ) left = mid;
else right = mid - 1;
}
d[left+1] = min ( d[left+1] , r[n].p );
return left + 1;
}
int main ( )
{
int c = 1;
while (~scanf ( "%d" , &n ) )
{
for ( int i = 1 ; i <= n ; i++ ) scanf ( "%d%d" , &r[i].r , &r[i].p );
sort ( r+1 , r+n+1 );
memset ( d , 0x3f , sizeof ( d ) );
d[0] = 0;
int ans = 0;
for ( int i = 1 ; i <= n ; i++ )
ans = max ( ans , get( i ) );
char s[50];
if ( ans > 1 ) sscanf ( "roads" , "%s" , s );
else sscanf ( "road" , "%s" , s );
printf ( "Case %d:\n" , c++ );
printf ( "My king, at most %d %s can be built.\n" , ans ,s );
puts ( "" );
}
}