HDU 5748 最长上升子序列的长度nlogn(固定尾部)

2023-02-12,,,,

Bellovin

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 858    Accepted Submission(s): 395

Problem Description
Peter has a sequence a1,a2,...,an and he define a function on the sequence -- F(a1,a2,...,an)=(f1,f2,...,fn), where fi is the length of the longest increasing subsequence ending with ai.

Peter would like to find another sequence b1,b2,...,bn in such a manner that F(a1,a2,...,an) equals to F(b1,b2,...,bn). Among all the possible sequences consisting of only positive integers, Peter wants the lexicographically smallest one.

The sequence a1,a2,...,an is lexicographically smaller than sequence b1,b2,...,bn, if there is such number i from 1 to n, that ak=bk for 1≤k<i and ai<bi.

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

The first contains an integer n (1≤n≤100000) -- the length of the sequence. The second line contains n integers a1,a2,...,an (1≤ai≤109).

 
Output
For each test case, output n integers b1,b2,...,bn (1≤bi≤109) 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

 
Source
BestCoder Round #84
 
题意:给一个序列,求出每个位置结尾的最长上升子序列;然后找一个字典序最小的这个函数值相同的子序列;
其实就是求每个位置结尾的最长上升子序列的长度组成的序列。
 
题解:固定尾部的最长上升子序列的长度nlgn处理
exm[j] 表示长度为j的的序列的最后一个值的大小
lower_bound的使用 返回第一个大于等于key的位置 确保严格的上升
这是为什么呢? 找到相同的值结尾的序列 长度却没有变 保证了严格上升
不同于最长不下降(使用upper_bound 跳过了相同的值 也就是长度增加了)。
理解
 

 /******************************
code by drizzle
blog: www.cnblogs.com/hsd-/
^ ^ ^ ^
O O
******************************/
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
#include<cmath>
#define ll __int64
#define PI acos(-1.0)
#define mod 1000000007
using namespace std;
int t;
int a[];
int ans[];
int n;
int main()
{
scanf("%d",&t);
{
for(int i=; i<=t; i++)
{
scanf("%d",&n);
scanf("%d",&a[]);
ans[]=;
int exm[];
int top=;
exm[]=a[];
for(int j=; j<n; j++)
{
scanf("%d",&a[j]); if(a[j]>exm[top])
{
top=top+;
exm[top]=a[j];
ans[j]=top;
}
else
{
int pos=lower_bound(exm,exm+top,a[j])-exm;
exm[pos]=a[j];
ans[j]=pos;
}
}
for(int j=; j<n; j++)
{
if(j==)
printf("%d",ans[j]);
else
printf(" %d",ans[j]);
}
printf("\n");
}
}
return ;
}

HDU 5748 最长上升子序列的长度nlogn(固定尾部)的相关教程结束。

《HDU 5748 最长上升子序列的长度nlogn(固定尾部).doc》

下载本文的Word格式文档,以方便收藏与打印。