这题坑点挺多。
首先,输入很大,虽然看懂了是最长上升子序列,但第一次用朴素查找,妥妥的超时了。。
学习一下二分查找LIS,可以优化到O(nlogn)。
还有就是英文输出时,一定要注意复数复数!!之前有道题也是用到各种数序的英文输出。不注意的话就会WA。
二分查找LIS,其实就是拿一个数组f[],下标表示长度,存放该长度序列的末尾数。该数组存放的末尾数也一定是递增的。
#include<iostream>
#include<algorithm>
#define max(a,b) a>b?a:b
using namespace std;
static int f[500002];
static int nd[500002];
int n;
int main(){
int fm,to,maxr,kcase = 1;;
while(~scanf("%d",&n)){
for(int i = 0;i<n;i++){
scanf("%d%d",&fm,&to);
nd[fm] = to;
}
int len = 1;
f[1] = nd[1];
for(int i = 2;i<=n;i++){
int low = 1,high = len,mid;
//二分法优化
while(low <= high){
int mid = (high + low)/2;
if(f[mid]<nd[i]){
low = mid+1;
}
else{
high = mid-1;
}
}
//这里是找到了最小的大于nd[i]的数
f[low] = nd[i]; //更新
len = low>len?low:len;
}
//这里复数也挺坑。。
if(len == 1){
printf("Case %d:\nMy king, at most 1 road can be built.\n\n",kcase);
}
else{
printf("Case %d:\nMy king, at most %d roads can be built.\n\n",kcase,len);
}
kcase++;
}
return 0;
}