1. 程式人生 > >HDU1025-二分求LIS。

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;
}