原题连接:
http://acm.hdu.edu.cn/showproblem.php?pid=1025
最长严格上升子序列的一个变形。思路:1.用a[p]=r表示p和r之间需要造路;
2.用dp[i]=j表示长度为i的严格上升子序列的最小尾数
3.用二分法查找满足dp[len-1]<a[i]<dp[len]的位置,将dp[len]改为a[i]
#include <iostream>
using namespace std;
int Binary_Search(int a[],int dp[],int pos,int max_len)
{
int left=1,right=max_len,mid;
while(left<right)
{
mid=(left+right)/2;
if(a[pos]<=dp[mid-1])right=mid-1;
else if(a[pos]>=dp[mid])left=mid+1;
else return mid;
}
return left;
}
int main()
{
int case_num=0;
int n;
while(cin>>n)
{
case_num++;
int *a=new int[n+1];
int *dp=new int[n+1];//dp[i]=j表示长度为i的上升子序列的最小尾数字为j
int max_len=0;//最大的长度
int i,j;
a[0]=dp[0]=0;
for(int count=1;count<=n;count++)
{
cin>>i>>j;
a[i]=j;
}
for(int i=1;i<=n;i++)
{
if(a[i]>dp[max_len])
{
max_len++;
dp[max_len]=a[i];
}
else
{
int len=Binary_Search(a,dp,i,max_len);//len满足dp[len-1]<a[i]<dp[len]
dp[len]=a[i];
}
}
cout<<"Case "<<case_num<<":"<<endl;
cout<<"My king, at most "<<max_len<<" road";
if(max_len>1)cout<<"s";
cout<<" can be built."<<endl<<endl;
}//end of while
return 0;
}