HDU - 1025 Constructing Roads In JGShining's Kingdom (nlogn 最长上升子序列

题意:

求最长上升子序列,但这个要用二分法:

博客参考:https://blog.csdn.net/idealistic/article/details/52181408

#include<iostream>
using namespace std;
 
long d[500001],a[500001];  //d[i]用来存最长不降子序列 最后一个元素 
long find(long a,long left,long right)  //二分查找
{
	long mid;
	while(left<=right)
	{
		mid=(left+right)/2;
       if(a>d[mid])//偏小 
		   left=mid+1;
	   else
		   right=mid-1;
	}
	return left;
}
int main()
{
	long n,i,j,len,p,t,k=0;
	while(scanf("%d",&n)!=EOF)
	{
		k++;
		for(i=1;i<=n;i++)
		{scanf("%d%d",&j,&p);
		a[j]=p;}
		d[1]=a[1];
		len=1;//初始序列长度 
		for(i=2;i<=n;i++)   
		{
			t=find(a[i],1,len);   //找出a[i]的位置
			d[t]=a[i];            //更新d[t],使d[t]尽量是最小的,显而易见,dp[t]越小,后面的dp[k](k>t)更大的可能性就会越大 
			//为什么可以这样做?仔细观察,发现对于一个a[i],要判断它是否是某个不降子序列的元素,我们只需要拿它和前面的dp[j](j<len)比较即可,
			//由于dp[j]记录的是到a[j]为止的序列的最长不降子序列的最后一个元素,如果a[i]>dp[j]并且a[i].b<dp[j+1],
			//那么我们自然要用a[i]更新dp[j+1](很明显,最长子序列长度为j+1),而如果a[i]比dp[j]的值都大,
			//这说明a[i]可以接在所有的dp[j]后面,自然我们选择最长的dp[len],因此,加入之后,len的长度要自加1  
            if(t>len)            //因为d[len]都是最大的
				len++;
		}
   if(len==1)
     printf("Case %d:\nMy king, at most %d road can be built.\n\n",k,len);  //单数
   else
     printf("Case %d:\nMy king, at most %d roads can be built.\n\n",k,len);  //复数
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/81772991