hdu1025 最长上升子序列 O(nlogn)优化版

这题坑点挺多。

首先,输入很大,虽然看懂了是最长上升子序列,但第一次用朴素查找,妥妥的超时了。。

学习一下二分查找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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值