zoukankan      html  css  js  c++  java
  • 【清真dp】cf1144G. Two Merged Sequences

    成就:赛后在cf使用错误的贪心通过一题

    成就:在cf上赛后提交hack数据

    成就:在cf上赛后hack自己

    题目大意

    有一长度$n le 2 imes 10^5$的序列,要求判断是否能够划分为一个严格递增和一个严格递减的子序列并给出划分方案。


    题目分析

    错误的贪心

    截止现在(4.22),这一种错误贪心尚可以通过此题。

    算法流程:考虑处理出一个LIS和一个LDS,并检查剩下的元素是否为LDS/LIS.

    这个算法在随机构造下是基本没问题的(因此跑了47000+组随机数据才rand出一组反例)。

    事实上,如果枚举每一个LIS/LDS,这个做法就是显然正确的,但是复杂度会有相当影响(例如一个完全非法但是LIS/LDS非常多的数列)

    清真dp

    记$f_{i,0}$为:$i$处在一个上升子序列中,$1cdots i-1$的下降子序列最高为$f_{i,0}$;$f_{i,1}$同理。

    这个状态显然是需要贪心取最大/最小的,那么这个转移就可以做到$O(1)$,相当高效。

     1 #include<bits/stdc++.h>
     2 const int maxn = 200035;
     3 const int INF = 2e9;
     4 
     5 int n,a[maxn],p[maxn][2],f[maxn][2];
     6 
     7 int read()
     8 {
     9     char ch = getchar();
    10     int num = 0, fl = 1;
    11     for (; !isdigit(ch); ch=getchar())
    12         if (ch=='-') fl = -1;
    13     for (; isdigit(ch); ch=getchar())
    14         num = (num<<1)+(num<<3)+ch-48;
    15     return num*fl;
    16 }
    17 void print(int x, int c)
    18 {
    19     if (x > 1) print(x-1, p[x][c]);
    20     printf("%d ",c);
    21 }
    22 int main()
    23 {
    24     n = read();
    25     for (int i=1; i<=n; i++) a[i] = read();
    26     f[1][0] = INF, f[1][1] = -INF;
    27     for (int i=2; i<=n; i++)
    28     {
    29         f[i][0] = -INF, f[i][1] = INF;
    30         if (a[i] > a[i-1]&&f[i][0] < f[i-1][0]) f[i][0] = f[i-1][0], p[i][0] = 0;
    31         if (a[i] < a[i-1]&&f[i][1] > f[i-1][1]) f[i][1] = f[i-1][1], p[i][1] = 1;
    32         if (a[i] > f[i-1][1]&&f[i][0] < a[i-1]) f[i][0] = a[i-1], p[i][0] = 1;
    33         if (a[i] < f[i-1][0]&&f[i][1] > a[i-1]) f[i][1] = a[i-1], p[i][1] = 0;
    34     }
    35     if (f[n][0]!=-INF) puts("YES"), print(n, 0), exit(0);
    36     if (f[n][1]!=INF) puts("YES"), print(n, 1), exit(0);
    37     puts("NO");
    38     return 0;
    39 }

    END

  • 相关阅读:
    使用dom4j 解析xml
    xml schema 建立xml文档
    xml dtd 约束建立xml文档
    DBCP 连接池的使用
    c++面向过程和面向对象-C++编译器是如何管理类和对象的
    c++读取文本文件
    一个范围的两个数进行数位的累加,实现对两个数num1和num2的数位和相加
    C++批量注释代码段取消注释代码段快捷键
    利用MATLAB截取一张复杂图片中想要的区域
    python学习之路系列
  • 原文地址:https://www.cnblogs.com/antiquality/p/10732496.html
Copyright © 2011-2022 走看看