Luogu P1410 子序列

题目大意:

给定一个长度为\(N\)(\(N\)为偶数)的序列,]
问能否将其划分为两个长度为\(\frac{N}{2}\)的严格递增子序列,
输入一共有\(50\)组数据,每组数据保证\(N \leq 2*10^3\)

题目解法:

非常巧妙的一道\(DP\)题。
$f[i][j] $ 表示到了第\(i\)个位置,
第一个序列中有\(j\)个元素,第二个序列中最后一个元素大小为\(f[i][j]\)。
显然最小化\(f[i][j]\)是最优策略。
然后转移有两种:
( 1 )如果\(h[i]<h[i+1]\),那么\(i+1\)可以放入第一个序列:
\[f[i+1][j+1] = min(f[i+1][j+1]\ , \ f[i][j])\]
( 2 )如果\(f[i][j]<h[i+1]\),那么\(i+1\)可以放入第二个序列:
\[f[i+1][i+j-1] = min(f[i+1][i+j-1],h[i])\]
其实就是交换了第一个序列与第二个序列。

实现代码:

#include<bits/stdc++.h>
#define RG register
#define IL inline
#define _ 2005
#define INF 2147483640
using namespace std;

IL int gi(){
    RG int data = 0 , m = 1; RG char ch = 0;
    while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if(ch == '-'){m = 0; ch = getchar();}
    while(ch >= '0' && ch <= '9')
    {data = (data << 1) + (data << 3) + (ch ^ 48); ch = getchar(); }
    return ( m ) ? data : -data;
}

int f[_][_] , h[_] , n;

int main(){
    while(scanf("%d",&n) != EOF){
        for(RG int i = 1; i <= n; i ++)h[i] = gi();
        for(RG int i = 1; i <= n; i ++)
            for(RG int j = 0; j <= i; j ++)
                f[i][j] = INF;
        f[1][1] = -INF;
        for(RG int i = 1; i <= n; i ++)
            for(RG int j = 1; j <= i; j ++)
                if(f[i][j] != INF){
                    if(h[i] < h[i+1])
                        f[i+1][j+1] = min(f[i][j] , f[i+1][j+1]);
                    if(f[i][j] < h[i+1])
                        f[i+1][i-j+1] = min(f[i+1][i-j+1] , h[i]);
                }
        puts( (f[n][n/2]!=INF) ? "Yes!" : "No!" );
    }return 0;
}

原文地址:https://www.cnblogs.com/GuessYCB/p/8406505.html

时间: 2024-10-20 17:02:59

Luogu P1410 子序列的相关文章

洛谷P1410 子序列

P1410 子序列 题目描述 给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列, 输入输出格式 输入格式: 若干行,每行表示一组数据.对于每组数据,首先输入一个整数N,表示序列的长度.之后N个整数表示这个序列. 输出格式: 同输入行数.对于每组数据,如果存在一种划分,则输出“Yes!”,否则输出“No!“. 输入输出样例 输入样例#1: 6 3 1 4 5 8 7 6 3 2 1 6 5 4 输出样例#1: Yes! No! 说明 [数据范围] 共三组数据,每

【Luogu】P1410子序列(DP)

题目链接 我DP是真的菜啊啊啊啊啊! f[i][j]表示考虑前i个数,有i-j+1个数组成一个上升子序列,且不以i结尾的尾端最小值. 设a为j个数组成的序列,且以i结尾:b为i-j+1个数组成的序列,且不以i结尾. 从f[i][j]到f[i+1][j+1]的转移如下: 若a后面可以接上第i+1个数,那b就和原来一样.也就是f[i+1][j+1]=min(f[i+1][j+1],f[i][j]) 如果a后面不能接上第i+1个数,那就接到b上.也就是f[i+1][i-j+1]=min(f[i+1][

P1410 子序列

题目链接 题解: 如果不考虑长度限制,可以用二分图染色做. #include <bits/stdc++.h> # define LL long using namespace std; int n; int a[2001]; int col[2001]; struct Edge{ int to; int next; }e[2001*2001]; int head[2001]; int en; void add(int from, int to){ e[en].next=head[from];

洛谷 P1410 子序列(DP)

这题的题解的贪心都是错误的...正解应该是个DP 考虑有哪些有关的条件:两个序列的当前长度, 两个序列的末尾数, 把这些都压进状态显然是会GG的 考虑两个长度加起来那一位的数一定是其中一个序列的末尾, 而我们要末尾的数尽量小, 所以完全可以把这个DP缩成两维 设f[i][j]为当前选到第i位, a[i]选入第一个序列, 则末尾为a[i], 第一个序列长度为j, 则第二个序列长度为i-j时第二个序列末尾的数最小为多少. 则有 if(a[i]<a[i+1]) f[i+1][j+1]=min(f[i+

Luogu 1439 【模板】最长公共子序列

题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子序列的长度 输入输出样例 输入样例#1: 5 3 2 1 4 5 1 2 3 4 5 输出样例#1: 3 说明 [数据规模] 对于50%的数据,n≤1000 对于100%的数据,n≤100000 [题解] 首先不难想到的是将其转化成一个序列的最长上升子序列 由于两个序列均为1~n的排列,在将其中一个

luogu P3402 最长公共子序列

题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: 给定两个长度分别为n和m的序列,序列中的每个元素都是正整数.保证每个序列中的各个元素互不相同.求这两个序列的最长公共子序列的长度. DJL最讨厌重复劳动,所以不想做那些做过的题.于是他找你来帮他做作业. 输入输出格式 输入格式: 第一行两个整数n和m,表示两个数列的长度. 第二行一行n个整数a

【luogu 1439 最长公共子序列】

题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子序列的长度 输入输出样例 输入样例#1: 复制 5 3 2 1 4 5 1 2 3 4 5 输出样例#1: 复制 3 说明 [数据规模] 对于50%的数据,n≤1000 对于100%的数据,n≤100000 [题解]       ①LCS->LIS       ②树状数组维护nlogn LIS #i

【Luogu】P2766最长不下降子序列问题(暴力网络流)

题目链接 水题qwq,数据都那么水. 我要是出数据的人我就卡$n^3$建图. qwq. 然而这么水的题我!居!然!没!有!1!A!!还!提!交!了!五!遍!!! md从现在开始要锻炼1A率了 看我从今往后做完一道题之后至少检查TM十分钟 可恶qwq. 第一问$n^2$sbDP可解.然而你们知道我提交五遍TM是错在哪里了吗????? 我TM就错在这个pj-,sb到不能再sb的sb暴力DP上!!! 气死我了!!! 关于第二问和第三问,先拆点再拆点qwq. 先把每个点拆成入点和出点用来限制流量,然后把

最长公共子序列(luogu 1439)

题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子序列的长度 输入输出样例 输入样例 5 3 2 1 4 5 1 2 3 4 5 输出样例 3 说明 [数据规模] 对于50%的数据,n≤1000 对于100%的数据,n≤100000 瞬时记忆 O(nlogn) 做法,意思大概是先把一个 a 序列映射到一个数组(似乎是叫做离散化),然后用它-- 代码