传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5748
Bellovin
Accepts: 428
Submissions: 1685
Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
Peter有一个序列a1,a2,...,an. 定义F(a1,a2,...,an)=(f1,f2,...,fn), 其中fi是以ai结尾的最长上升子序列的长度. Peter想要找到另一个序列b1,b2,...,bn使得F(a1,a2,...,an)和F(b1,b2,...,bn)相同. 对于所有可行的正整数序列, Peter想要那个字典序最小的序列. 序列a1,a2,...,an比b1,b2,...,bn字典序小, 当且仅当存在一个正整数i (1≤i≤n)满足对于所有的k (1≤k<i)都有ak=bk并且ai<bi.
输入描述
输入包含多组数据, 第一行包含一个整数T表示测试数据组数. 对于每组数据: 第一行包含一个整数n (1≤n≤100000)表示序列的长度. 第二行包含n个整数a1,a2,...,an (1≤ai≤109).
输出描述
对于每组数据, 输出n个整数b1,b2,...,bn (1≤bi≤109)表示那个字典序最小的序列.
输入样例
3 1 10 5 5 4 3 2 1 3 1 3 5
输出样例
1 1 1 1 1 1 1 2 3
Peter有一个序列a1,a2,...,an. 定义F(a1,a2,...,an)=(f1,f2,...,fn), 其中fi是以ai结尾的最长上升子序列的长度. Peter想要找到另一个序列b1,b2,...,bn使得F(a1,a2,...,an)和F(b1,b2,...,bn)相同. 对于所有可行的正整数序列, Peter想要那个字典序最小的序列. 序列a1,a2,...,an比b1,b2,...,bn字典序小, 当且仅当存在一个正整数i (1≤i≤n)满足对于所有的k (1≤k<i)都有ak=bk并且ai<bi说的太难理解了 简单点就是要找a数组中每个元素的最长上升子序列
解题思路:
定义一个l数组,初始化都为最大值。再循环输入的数。找到l数组中第一个比a大的数,记录下标即可。
8 | ||||||||
num[i] | 1 | 5 | 4 | 7 | 9 | 10 | 8 | 11 |
dp[i] | 1 | 2 | 2 | 3 | 4 | 5 | 4 | 6 |
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
a[i] | INF | INF | INF | INF | INF | INF | INF | INF |
ans相等时替换 | 1 | INF | INF | INF | INF | INF | INF | INF |
更替 | 1 | 5 | INF | INF | INF | INF | INF | INF |
更替 | 1 | 4 | INF | INF | INF | INF | INF | INF |
更替 | 1 | 4 | 7 | 9 | 10 | INF | INF | INF |
更替 | 1 | 4 | 7 | 8 | 10 | INF | INF | INF |
更替 | 1 | 4 | 7 | 8 | 10 | 11 | INF | INF |
#include<cstdio>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int dp[100050],a[100050],num[100050];
int t,n;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
// fill(a,a+n,INF)
for(int i=1; i<=n; i++)
{
scanf("%d",&num[i]);
dp[i]=0;
a[i]=INF;
}
for(int i=1; i<=n; i++)
{
int ans=lower_bound(a+1, a+n+1, num[i]) - a;//得到 a 数组中的第一个比 num【i】 大的数;
dp[i]=ans;
a[ans]=num[i]; //???将num【i】数组里的数放入(置换)充满 INF的 a 数组中 方便下次查找可以找到
} //???即使得到的 ans 和上一个相等 即 a【ans】相等也没事 因为找的是最长上升的子序列 即使相等也不影响查找
for(int i=1; i<n; i++)
printf("%d ",dp[i]);
printf("%d\n",dp[n]);
}
return 0;
}
//5
//8
//1 5 4 7 9 10 8 11
//1 2 2 3 4 5 4 6