题目大意:给出N,表示有N组需求,每组需求r ,q 表示贫穷城市需要发达城市的资源,更具这N组需求修建铁路,铁路不能交叉,求出最多可修多少条铁路?
算法思想:
将N组需求按r从小到大排序,之后将q序列的最长上升子序列。此题因为数据量比较大,所以需要NlogN 的算法。
用一个b[]数组,b[i]记录长度为i的上升序列中最后一个元素的最小值,在算法过程中,b[]数组是在不断更新的,如果a[i]>=b[k]则b[k+1]=a[i],否则则寻找a[i]在b[]数组中的位置pos,并且更新b[pos].
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=500100;
typedef struct{
int p;
int r;
} City;
City c[MAXN];
int a[MAXN];
int b[MAXN];//记录序列长度为i时的第i个数的最小值
int dp[MAXN];
bool cmp(City a,City b){
if(a.p<b.p) return true;
return false;
}
/*二分搜索:寻找a[i]正确的插入位置*/
int Binary_Search(int num,int k){
int l=1,r=k;
while(l<=r){
int m=(l+r)/2;
if(num>=b[m])
l=m+1;
else
r=m-1;
}
return l;
}
/*求最长公共子序列*/
int LIS(int a[],int n){
int k=1;
dp[1]=1;b[1]=a[1];
for(int i=2;i<=n;i++){
if(a[i]>=b[k])
b[++k]=a[i];
else//跟新b[pos]的最小值
{
int pos=Binary_Search(a[i],k);
b[pos]=a[i];
}
}
return k;
}
int main(){
int n,t=1;
while(cin>>n){
for(int i=1;i<=n;i++ ){
cin>>c[i].p>>c[i].r;
}
sort(c+1,c+1+n,cmp);//将n对需求排序
for(int i=1;i<=n;i++){//将排好序的发达城市存入a[]中
a[i]=c[i].r;
}
int ans=LIS(a,n);
cout<<"Case "<<t++<<":"<<endl;
cout<<"My king, at most "<<ans;
if(ans==1)
cout<<" road can be built."<<endl<<endl;
else
cout<<" roads can be built."<<endl<<endl;
}
return 0;
}