【HDU5748】Bellovin

Description

Peter has a sequence  and he define a function on the sequence -- , where  is the length of the longest increasing subsequence ending with 

Peter would like to find another sequence  in such a manner that  equals to . Among all the possible sequences consisting of only positive integers, Peter wants the lexicographically smallest one. 

The sequence  is lexicographically smaller than sequence , if there is such number  from  to , that  for  and .

Input

There are multiple test cases. The first line of input contains an integer , indicating the number of test cases. For each test case: 

The first contains an integer   -- the length of the sequence. The second line contains  integers  .

Output

For each test case, output  integers   denoting the lexicographically smallest sequence. 

Sample Input

3
1
10
5
5 4 3 2 1
3
1 3 5

Sample Output

1
1 1 1 1 1
1 2 3

【题解】

这题就是要求最长不下降子序列。

不同的是,它不是要求你求出来最长不下降子序列的各个值具体是什么。

它要求的是以ai结尾的最长不下降子序列的长度f[i].

但是这题的坑点在于。它不让你用那么方便的n^2算法。要用nlogn算法才行。所以就去找咯。

原来的f[i]要改一下意思了。变成长度为i的最长上升(严格上升)序列的最后一个元素的最小值是啥。

一开始len = 1;f[1] = a1;

然后for i = 2->n 

if (a[i] > f[len]) //这个很好理解吧?就是如果大于长度为len的最后一个元素.则最长XX的长度递增。

{
len++; 

f[len] = a[i]; //然后把新的元素接上去就好

直接输出len.表示以a[i]结尾的最长不下降子序列的长度为len;

}

else

{

找到一个k

f[k-1]<a[i]<=f[k];

因为a[i] <= f[k]且f[k-1]<a[i] 则说明其可以代替f[k]成为一个更小的f[k]'。

那么就让f[k] = a[i]就好;

这个k可以用二分查找找到(鬼才想去写这个二分查找。跟屎一样难写!)

所以我们用STL解决(就是algorithm这个头文件里的东西。)

它叫。我看下我能不能默下来lower__count??

我看下。

哦,错了

是lower_bound(f+1,f+1+len,a[i])-f;

你没看错最后面减去了一个数组

然后前面就是类似sort(a+1,a+1+len);

表示从1..len找到这样的k;

然后f[k] = a[i];

然后输出k.表示以a[i]为结尾的最长不下降子序列的长度为k;

}

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

int t, n, a[100001], f[100001], last = 1, ans[100001];

int main()
{
	scanf("%d", &t);
	for (int mm = 1; mm <= t; mm++)
	{
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)//读入数据
			scanf("%d", &a[i]);
		f[1] = a[1];//最长不下降子序列长度为1的最小结尾元素一开始就是a[1]
		ans[1] = 1;//没用的。。别管
		printf("1");//表示以a1为结尾的最长不下降子序列的长度为1
		last = 1;
		for (int i = 2; i <= n; i++)
		{
			if (f[last] < a[i])//因为更新了最长不下降子序列的长度
			{
				last++;
				printf(" %d", last);//所以以其结尾的元素的长度为last;
				f[last] = a[i];
			}
			else
			{
				int pos = lower_bound(f + 1, f + 1 + last, a[i]) - f;//找到合适的K值
				f[pos] = a[i];//放在这个位置
				printf(" %d", pos);//输出它的长度、即以a[i]为结尾的最长不下降子序列的长度。
			}
		}
		printf("
");
	}
	return 0;
}


原文地址:https://www.cnblogs.com/AWCXV/p/7632288.html