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 i.
Input
There are multiple test cases. The first line of input contains an integer ).
Output
For each test case, output ) 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
题意:给一个序列,求出每个位置结尾的最长上升子序列;然后找一个字典序最小的这个函数值相同的子序列;
其实就是求每个位置结尾的最长上升子序列的长度组成的序列。
题解:固定尾部的最长上升子序列的长度nlgn处理
exm[j] 表示长度为j的的序列的最后一个值的大小
lower_bound的使用 返回第一个大于等于key的位置 确保严格的上升
这是为什么呢? 找到相同的值结尾的序列 长度却没有变 保证了严格上升
不同于最长不下降(使用upper_bound 跳过了相同的值 也就是长度增加了)。
理解
1 /****************************** 2 code by drizzle 3 blog: www.cnblogs.com/hsd-/ 4 ^ ^ ^ ^ 5 O O 6 ******************************/ 7 //#include<bits/stdc++.h> 8 #include<iostream> 9 #include<cstring> 10 #include<cstdio> 11 #include<map> 12 #include<algorithm> 13 #include<cmath> 14 #define ll __int64 15 #define PI acos(-1.0) 16 #define mod 1000000007 17 using namespace std; 18 int t; 19 int a[100005]; 20 int ans[100005]; 21 int n; 22 int main() 23 { 24 scanf("%d",&t); 25 { 26 for(int i=1; i<=t; i++) 27 { 28 scanf("%d",&n); 29 scanf("%d",&a[0]); 30 ans[0]=1; 31 int exm[100005]; 32 int top=1; 33 exm[1]=a[0]; 34 for(int j=1; j<n; j++) 35 { 36 scanf("%d",&a[j]); 37 38 if(a[j]>exm[top]) 39 { 40 top=top+1; 41 exm[top]=a[j]; 42 ans[j]=top; 43 } 44 else 45 { 46 int pos=lower_bound(exm,exm+top,a[j])-exm; 47 exm[pos]=a[j]; 48 ans[j]=pos; 49 } 50 } 51 for(int j=0; j<n; j++) 52 { 53 if(j==0) 54 printf("%d",ans[j]); 55 else 56 printf(" %d",ans[j]); 57 } 58 printf("\n"); 59 } 60 } 61 return 0; 62 }