HDU1025-二分求LIS。

1.题目链接。说了很多,但是一句话可以概括。在平行线的之间有一些线段,取一组线段使得任意两条不相交,求最多有多少条这样的线段。

2.分析:为什么就是转化成了LIS了呢?其实这个很简单,我们只需要考虑一条边,从1到n,然后把另一条边上的数字映射上来,并且是一一对应的,所以就是个数组了。a[i]=j;代表i和j之间有一条线段,做完这个映射之后,我们可以观察到,如果在poor cities中,i<j的,那么如果二者不相交,就a[i]就必然是小于a[j]的。就是一种偏序关系。知道了这个,求最多满足的那么就是求LIS了,但是如果只是普通的n2的做法,必然是不行的,这里我们采用二分将复杂度下降为nlogn即可。下面是代码:

#include<iostream>
#include<algorithm>
#pragma warning(disable:4996)
int dp[50005], a[50005];//dp[i]表示已a[i]为结尾的最长的上身子序列的最后一个数据
//找长度为n的最长的上升子序列

int Lis(int n)
{
	int len = 1, i, low, high, mid;
	dp[1] = a[1];
	for (i = 2; i <= n; i++)
	{
		low = 1;
		high = len;
		while (low <= high)
		{
			mid = (low + high) / 2;
			if (a[i]>dp[mid])
				low = mid + 1;
			else
				high = mid - 1;
		}
		dp[low] = a[i];
		if (low>len)
			len = low;
	}
	return len;
}
int main()
{
	int n, x, y, i, ans, k = 1;
	while (scanf("%d", &n) != EOF)
	{
		for (i = 0; i<n; i++)
		{
			scanf("%d%d", &x, &y);
			a[x] = y;
		}
		ans = Lis(n);
		printf("Case %d:\n", k++);
		if (ans == 1)
			printf("My king, at most 1 road can be built.\n");
		else
			printf("My king, at most %d roads can be built.\n", ans);
		printf("\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/85545375