首页 > 其他 > 详细

JZYZOJ1261 字典序最小的lis

时间:2017-11-04 17:10:08      阅读:199      评论:0      收藏:0      [点我收藏+]
 

求字典序方法:

f[i]表示i位数字的最长上升子序列长度,len为最长上升子序列长度,ans[t]为第t位答案,maxn为ans[t+1](初始化为最大值)
倒序查找f[i]==t&&a[i]<maxn的a[i],每找到一个则存入答案,t--;
 
原理:显然a[i]前不可能有一个a[j]<a[i]&&f[j]>=f[i]的a[j],所以倒序可行
 
技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int bn=50010;
 8 int n,len;
 9 long long a[bn]={},f[bn]={},g[bn]={},ans[bn]={};
10 inline int search(int x){
11     int left=0,right=len,mid;
12     while(left+1<right){
13         mid=(left+right)/2;
14         if(a[g[mid]]<x){
15             left=mid;
16         }
17         else{
18             right=mid;
19         }
20     }
21     if(a[g[right]]<x){
22         left=right;
23     }
24     return left;
25 }
26 int main(){
27     //freopen("wtf.in","r",stdin);
28     int i=1;
29     while(cin>>a[i]){
30         i++;
31     }
32     n=i-1;
33     a[0]=-9999999999LL;
34     f[1]=1;
35     g[1]=1;
36     len=1;
37     for(int i=2;i<=n;i++){
38         if(a[i]>a[g[len]]){
39             len++;
40             g[len]=i;
41             f[i]=len;
42         }
43         else{
44             int t=search(a[i]);
45             f[i]=t+1;
46             if(a[g[t+1]]>a[i]){
47                 g[t+1]=i;
48             }
49         }
50     }
51     int t=len;
52     long long maxn=9999999999LL;
53     for(int i=n;i>=1;i--){
54         if(!t){
55             break;
56         }
57         if(f[i]==t&&a[i]<maxn){
58             maxn=a[i];
59             ans[t]=a[i];
60             t--;
61         }
62     }
63     for(int i=1;i<=len;i++){
64         printf("%d ",ans[i]);
65     }
66     cout<<endl;
67     return 0;
68 }
View Code

 

JZYZOJ1261 字典序最小的lis

原文:http://www.cnblogs.com/137shoebills/p/7783698.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!