• 【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列


    nlogn求出最长上升子序列长度。

    对每次询问,贪心地回答。设输入为x。当前数a[i]可能成为答案序列中的第k个,则若 f[i]>=x-k && a[i]>ans[k-1] 即可。

    f[i]表示以a[i]开头的最长上升子序列长度。

    但这个东西难以统计。so 我们将原序列反序,求f[i] 表示以 a[i]为结尾的最长下降子序列长度即可。最后再将f、a reverse一下。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int a[10001],n,m,en=1,len,last;
     5 int b[10001];//b[i]:将a翻转后,长度为i的最长下降子序列的末尾
     6 int c[10001];//c[i]:将a翻转后,以a[i]开头的最长下降子序列的长度
     7 bool cmp(const int &a,const int &b){return a>b;}
     8 int main()
     9 {
    10     scanf("%d",&n);
    11     for(int i=1;i<=n;i++) scanf("%d",&a[n-i+1]);
    12     scanf("%d",&m);
    13     b[1]=a[1]; c[1]=1;
    14     for(int i=2;i<=n;i++)
    15       {
    16           int *p=lower_bound(b+1,b+en+1,a[i],cmp);
    17           if(!(*p)) ++en;
    18           *p=a[i];
    19           c[i]=p-b;
    20       }
    21     for(int i=1;i<=(n>>1);i++) swap(c[i],c[n-i+1]),swap(a[i],a[n-i+1]);
    22     for(int i=1;i<=m;i++)
    23       {
    24           scanf("%d",&len);
    25           if(len>en)
    26             {
    27                 puts("Impossible");
    28                 continue;
    29             } last=0;
    30           for(int j=1;j<=n;++j)
    31             if(c[j]>=len&&a[j]>last)
    32               {
    33                 printf("%d",last=a[j]);
    34                 if(!(--len))
    35                   {
    36                     puts("");
    37                     break;
    38                   } putchar(' ');
    39               }
    40       }
    41     return 0;
    42 }
  • 相关阅读:
    数据结构 链表笔记
    C语言 字符串操作 笔记
    数据结构 排序算法 笔记
    链表详解
    mysql常用命令
    图片压缩工具之grunt-contrib-imagemin
    正则表达式
    阿里云部署nodejs服务器(windows)
    canvas简介
    js面向对象
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4115579.html
Copyright © 2020-2023  润新知