• [Luogu 1410]子序列


    Description

    给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列,

    Input

    若干行,每行表示一组数据。对于每组数据,首先输入一个整数N,表示序列的长度。之后N个整数表示这个序列。

    Output

    同输入行数。对于每组数据,如果存在一种划分,则输出“Yes!”,否则输出“No!“。

    Sample Input

    6 3 1 4 5 8 7
    6 3 2 1 6 5 4

    Sample Output

    Yes!
    No!

    HINT

    共三组数据,每组数据行数<=50,0 <= 输入的所有数 <= 10^9

    第一组(30%):N <= 20

    第二组(30%):N <= 100

    第三组(40%):N <= 2000

    题解

    在前$i$位中找长$j$位的以第$i$位结尾的上升子序列(我们设这个为序列$A$),并且剩下的也是上升子序列(设这个为序列$B$),那么$f[i][j]$表示剩下的(即前i位中长$i-j$位的不以第$i$位结尾的)上升子序列(即序列$B$)的最后一位的最小值。

    注意:$A$一定是以最后一个数结尾的。

    然后转移:

    如果$a[i]<a[i+1]$,那么$f[i+1][j+1] = min(f[i+1][j+1], f[i][j])$,意思就是将$a[i+1]$接在序列$A$后,相当于可以直接把$f[i][j]$扩展到第$i+1$位。

    如果$f[i][j]<a[i+1]$,那么$f[i+1][i-j+1] = min(f[i+1][i-j+1], a[i])$,意思是将$a[i+1]$接在$B$后,相当于第$i+1$继承前$i$位中$i-j$位长的上升子序列,此时$B$序列的某尾为最后一个数,那么我们就要$swap(A,B)$。

     1 //It is made by Awson on 2017.9.27
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime> 
     6 #include <queue>
     7 #include <stack>
     8 #include <string>
     9 #include <cstdio>
    10 #include <vector>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define Min(a, b) ((a) < (b) ? (a) : (b))
    16 #define Max(a, b) ((a) > (b) ? (a) : (b))
    17 #define LL long long
    18 using namespace std;
    19 const int N = 2000;
    20 void read(int &x) {
    21     char ch; bool flag = 0;
    22     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    23     for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    24     x *= 1-2*flag;
    25 }
    26 
    27 int n, a[N+5];
    28 int f[N+5][N+5];
    29 
    30 void work() {
    31     for (int i = 1; i <= n; i++)
    32         read(a[i]);
    33     memset(f, 127, sizeof(f));
    34     int INF = f[0][0];
    35     f[1][1] = -1;
    36     for (int i = 1; i <= n; i++)
    37         for (int j = 0; j <= i; j++)
    38             if (f[i][j] != INF) {
    39                 if (a[i] < a[i+1]) f[i+1][j+1] = Min(f[i+1][j+1], f[i][j]);
    40                 if (f[i][j] < a[i+1]) f[i+1][i+1-j] = Min(f[i+1][i+1-j], a[i]);
    41             }
    42     printf(f[n][n/2] == INF ? "No!
    " : "Yes!
    ");
    43 }
    44 int main() {
    45     while (~scanf("%d", &n))
    46         work();
    47     return 0;
    48 }
  • 相关阅读:
    leetCode 61.Rotate List (旋转链表) 解题思路和方法
    aar格式
    hadoop生态系统学习之路(六)hive的简单使用
    centOS 7中上网以及网卡的一些设置
    Codeforces 223C Partial Sums 数论+组合数学
    项目管理:怎样让例会高效
    Web用户的身份验证及WebApi权限验证流程的设计和实现
    IIS7 经典模式和集成模式的区别分析
    JS实现密码加密
    discuz !NT 3.5 论坛整合 .net 网站用户登录,退出
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7603665.html
Copyright © 2020-2023  润新知