题意

这个DP状态有点神。

首先考虑一个最暴力的状态:\(f_{i,j,k,u}\)表示第一个选了\(i\)个,第二个选了\(j\)个,第一个结尾为\(k\),第二个结尾为\(u\)是否可行。

现在考虑消减状态:

1.首先知道了处理到第几个,那么只要知道一个长度就能推出另一个。 因此状态可以改为\(f_{i,j,k,u}\)表示处理到了第\(i\)个,第一个序列选了\(j\)个,第一个序列结尾为\(k\),第二个序列结尾为\(u\)是否可行。(这并没有减少维数,只是转化下,方便处理。)

2.既然所有的数都要选,假设当前处理到了第\(i\)个,那么第\(i-1\)个必定在结尾,因此我们可以消去一维:

\(f_{i,j,k}\)表示处理到第\(i\)个,结尾是\(a_i\)的那个序列长度为\(j\),另一个结尾为\(k\)是否可行。

3.贪心地想,一个序列结尾越小越容易接数,因此可以将一维放到DP的值中:

\(f_{i,j}\)表示处理到第\(i\)个,结尾是\(a_{i-1}\)的那个序列长度为\(j\),另一个结尾最小是多少。

现在我们已经将DP减到二维,于是就可以转移了:

\(a_i>a_{i-1}\):此时\(a_i\)可以拼接在\(a_{i-1}\)后面:

\(f_{i,j}=\min(f_{i,j}f_{i-1,j-1})\)。

\(a_i>f_{i-1,i-j}\):此时我们可以将\(a_i\)接到另一个序列后面,于是我们交换两个序列,因为另一个序列后面接了\(a_i\),我们要符合定义,于是可得:

\(f_{i,j}=\min(f_{i,j},a_{i-1})\)。

最后判断\(f_{n,n/2}\)是否为\(inf\)。

数据范围不知道,到某dark上看了看,\(n\leqslant2000\)。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2010;
int T,n;
int a[maxn];
int f[maxn][maxn];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
memset(f,0x3f,sizeof(f));
f[0][0]=-1;
for(int i=1;i<=n;i++)
for(int j=1;j<=min(n/2,i);j++)
{
if(a[i]>a[i-1])f[i][j]=min(f[i][j],f[i-1][j-1]);
if(a[i]>f[i-1][i-j])f[i][j]=min(f[i][j],a[i-1]);
}
puts(f[n][n/2]<0x3f3f3f3f?"Yes!":"No!");
}
return 0;
}

P4728 [HNOI2009]双递增序列的更多相关文章

  1. 【BZOJ1489】[HNOI2009]双递增序列(动态规划)

    [BZOJ1489][HNOI2009]双递增序列(动态规划) 题面 BZOJ 洛谷 题解 这\(dp\)奇奇怪怪的,设\(f[i][j]\)表示前\(i\)个数中,第一个数列选了\(j\)个数,第二 ...

  2. [HNOI2009]双递增序列(洛谷P4728)+小烈送菜(内部训练题)——奇妙的dp

    博主学习本题的经过嘤嘤嘤: 7.22 : 听学长讲(一知半解)--自己推(推不出来)--网上看题解--以为自己会了(网上题解是错的)--发现错误以后又自己推(没推出来)--给学长发邮件--得到正确解法 ...

  3. [luogu4728 HNOI2009] 双递增序列 (dp)

    传送门 Solution 前几天刚做了类似题,这种将一个序列拆分为两个单调序列的题一般都是设\(dp[i]\)表示i为一个单调序列的末尾时,另一个序列的末尾是多少 然后应用贪心的思想,在这道题中就是让 ...

  4. [HNOI2009]双递增序列(动态规划,序列dp)

    感觉这个题还蛮难想的. 首先状态特别难想.设\(dp[i][j]\)表示前i个数,2序列的长度为j的情况下,2序列的最后一个数的最小值. 其中1序列为上一个数所在的序列,2序列为另外一个序列. 这样设 ...

  5. [HNOI2009]双递增序列

    不难发现本题贪心是不好做的,可以考虑 \(dp\). 首先的一个想法就是令 \(dp_{i, j, k, l}\) 表示当前选到第 \(i\) 个位置,当前第一个序列选了 \(j\) 个数,当前第一个 ...

  6. luogu4728 双递增序列 (dp)

    设f[i][j]表示以i位置为第一个序列的结尾,第一个序列的长度为j,第二个序列的结尾的最小值 那么对于f[i][j],有转移$f[i+1][j+1]=min\{f[i+1][j+1],f[i][j] ...

  7. BZOJ 1489: [HNOI2009]双递增序( dp )

    dp(i, j)表示选第i个, 且当前序列长度为j, 另一个序列的最后一个元素的最小值...然后根据上一个是哪个序列选的讨论一下就行了...奇怪的dp... --------------------- ...

  8. [BZOJ 1489][HNOI2009]双递增序

    传送门 满满的负罪感,昨晚的刷题历程:写几道难题吧-->算了,还是只切道水题吧-->RNG赢了...... 背包一下就行了 #include <bits/stdc++.h> u ...

  9. ACM: Racing Gems - 最长递增序列

    Racing Gems   You are playing a racing game.  Your character starts at the x axis (y = 0) and procee ...

随机推荐

  1. 字符串模式匹配——KMP算法

    KMP算法匹配字符串 朴素匹配算法   字符串的模式匹配的方法刚开始是朴素匹配算法,也就是经常说的暴力匹配,说白了就是用子串去和父串一个一个匹配,从父串的第一个字符开始匹配,如果匹配到某一个失配了,就 ...

  2. Android 项目优化(一):项目代码规范优化

    项目代码规范为主要包含:类,常量,变量,ID等命名规范:注释规范:分包规范:代码风格规范. 项目代码规范是软件开发过程中非常重要的优化环节. 目前的开发社区提供了很多的开发规范文档,阿里巴巴推出了&l ...

  3. SpringCloud之Ribbon:负载均衡

    Spring Cloud集成了Ribbon,结合Eureka,可实现客户端的负载均衡. 下面实现一个例子,结构下图所示. 一.服务器端 1.创建项目 开发工具:IntelliJ IDEA 2019.2 ...

  4. Linux发行版的系统目录名称命名规则以及用途

    linux各种发行版都遵循LSB(Linux Stadards Base)规则,使用一致的相关的基础目录名称,使用根目录系统结构(root filesystem),使用FHS(Files Hierar ...

  5. python 基础学习笔记(4)--字典 和 集合

    **字典:** - [ ] 列表可以存储大量的数据,但是如果数据量大的话,他的查询速度比较慢,因为列表只能顺序存储,数据与数据之间的关联性不强.所以便有了字典(dict)这种容器的数据类型,它是以{} ...

  6. spring boot 加入mail邮件支持

    一.添加依赖 <!-- 邮件整合 --> <dependency> <groupId>org.springframework.boot</groupId> ...

  7. openpyxl基本操作

    参考资料:OpenPyXL的使用教程(一) openpyxl 基本操作 # 创建xml from openpyxl import Workbook # 创建工作簿 wb = Workbook() # ...

  8. ubuntu 安装谷歌浏览器

    如何在ubuntu 中安装谷歌浏览器, 对于一个刚刚接触ubuntu的人来说,希望安装软件更加的简单,明了.最好能够像在windows下面安装软件一样. 先来介绍一下如何快速的安装谷歌浏览器,以下的方 ...

  9. go语言之切片即动态数组

    切片和数组的类型有什么不一样,我们可以打印一下,就可以知道两者的区别了,数组是容量的,所以中括号中有容量,切片的动态数组,是没有容量,这是数组和切片最大的区别 test8_4 := [20] int ...

  10. HttpModules配置事项

    前沿:还是那句话 ASP.NET管道,浏览器 - isAPI32.dll - HttpModules - HttpHandler - 返回客户端Web.Config:<httpModules&g ...