Bellovin
HDU - 5748Peter 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
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)
3 1 10 5 5 4 3 2 1 3 1 3 5
1 1 1 1 1 1 1 2 3
思路:字典序最小其实就是a序列的LIS
其思想源自最长上升子系列的lower_bound的优化 最长上升子序列问题l#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int a[100100];
int dp[100100];//dp[i]储存长度为i的上升子序列中末尾元素最小值
int ans[100100];
int n;
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
int i;
for(i = 1; i <= n; i++){
scanf("%d",&a[i]);
dp[i] = INF;
}
int pos;
//这道题不是让求最长上升子序列,而是求出以每个元素为末尾时的最长上升序列
for(i = 1; i <= n; i++){
pos = lower_bound(dp+1,dp+1+n,a[i])-dp;//每次查找
ans[i] = pos;//记录位置
dp[pos] = a[i];//更新dp数组
}
for(i = 1; i <= n; i++){
if(i==1)
printf("%d",ans[i]);
else
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}