题目链接

\(Description\)

\(Solution\)

合法的子序列只有三种情况:递增,递减,前半部分递增然后一直递减(下去了就不会再上去了)(当然还要都满足\(|a_{i+1}-a_i|=1\))。

容易想到区间DP。\(f[i][j]\)表示把区间\([i,j]\)全部删除的最大收益,还需要\(g[i][j]\)表示将区间\([i,j]\)删成连续上升的一段(\(a_i\sim a_j\))的最大收益,\(h[i][j]\)表示将区间\([i,j]\)删成连续下降的一段(\(a_i\sim a_j\))的最大收益。

那么\(g[i][j]\)的元素个数就是\(a_j-a_i+1\),\(h[i][j]\)的元素个数为\(a_i-a_j+1\),合并\(g[i][k],h[k][j]\)后的元素个数就是\(2a_k-a_i-a_j+2-1\)(减掉1个\(a_k\))。

那么$$f[i][j]=\max{f[i][k]+f[k+1][j],\ g[i][k]+h[k][j]+v[2a_k-a_i-a_j+1]}$$

其实\(g,h\)用一个数组就可以了,因为只需要判断一下\(a_i,a_j\)的大小关系,就知道是上升序列还是下降序列了。

最后的答案就是\(f\)的最大子段和。\(n^2\)求出来即可。

//78ms	1100KB
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=405,INF=0x3f3f3f3f; int A[N],val[N],f[N][N],g[N][N],dp[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
} int main()
{
int n=read();
for(int i=1; i<=n; ++i) val[i]=read();
for(int i=1; i<=n; ++i) A[i]=read(); for(int i=1; i<=n; ++i)
{
f[i][i]=val[1], g[i][i]=0;
for(int j=i+1; j<=n; ++j) f[i][j]=g[i][j]=-INF;
} for(int len=1; len<n; ++len)
for(int i=1; i+len<=n; ++i)
{
int j=i+len;
for(int k=i; k<j; ++k)
{
f[i][j]=std::max(f[i][j],f[i][k]+f[k+1][j]);
if((A[i]<A[j] && A[j]==A[k]+1)||(A[i]>A[j] && A[j]==A[k]-1))
g[i][j]=std::max(g[i][j],g[i][k]+f[k+1][j-1]);
}
for(int k=i; k<=j; ++k)
if(A[k]>=A[i] && A[k]>=A[j] && 2*A[k]-A[i]-A[j]+1<=n)//这东西显然不会<=0啊
f[i][j]=std::max(f[i][j],g[i][k]+g[k][j]+val[2*A[k]-A[i]-A[j]+1]);
}
for(int i=1; i<=n; ++i)
{
dp[i]=dp[i-1];
for(int j=1; j<=i; ++j) dp[i]=std::max(dp[i],dp[j-1]+f[j][i]);
}
printf("%d\n",dp[n]); return 0;
}

Codeforces.392E.Deleting Substrings(区间DP)的更多相关文章

  1. Codeforces - 149D 不错的区间DP

    题意:有一个字符串 s. 这个字符串是一个完全匹配的括号序列.在这个完全匹配的括号序列里,每个括号都有一个和它匹配的括号 你现在可以给这个匹配的括号序列中的括号染色,且有三个要求: 每个括号只有三种情 ...

  2. Codeforces 983B. XOR-pyramid【区间DP】

    LINK 定义了一种函数f 对于一个数组b 当长度是1的时候是本身 否则是用一个新的数组(长度是原数组-1)来记录相邻数的异或,对这个数组求函数f 大概是这样的: \(f(b[1]⊕b[2],b[2] ...

  3. CodeForces - 1025D: Recovering BST (区间DP)

    Dima the hamster enjoys nibbling different things: cages, sticks, bad problemsetters and even trees! ...

  4. Codeforces 1114D Flood Fill (区间DP or 最长公共子序列)

    题意:给你n个颜色块,颜色相同并且相邻的颜色块是互相连通的(连通块).你可以改变其中的某个颜色块的颜色,不过每次改变会把它所在的连通块的颜色也改变,问最少需要多少次操作,使得n个颜色块的颜色相同. 例 ...

  5. Codeforces 958C3 - Encryption (hard) 区间dp+抽屉原理

    转自:http://www.cnblogs.com/widsom/p/8863005.html 题目大意: 比起Encryption 中级版,把n的范围扩大到 500000,k,p范围都在100以内, ...

  6. CodeForces 149D Coloring Brackets 区间DP

    http://codeforces.com/problemset/problem/149/D 题意: 给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色,上蓝色 2 ...

  7. codeforces 149D Coloring Brackets (区间DP + dfs)

    题目链接: codeforces 149D Coloring Brackets 题目描述: 给一个合法的括号串,然后问这串括号有多少种涂色方案,当然啦!涂色是有限制的. 1,每个括号只有三种选择:涂红 ...

  8. CodeForces - 983B XOR-pyramid(区间dp,异或)

    XOR-pyramid time limit per test 2 seconds memory limit per test 512 megabytes input standard input o ...

  9. Codeforces 607B Zuma(区间DP)

    题目大概说,有n个颜色的宝石,可以消除是回文串的连续颜色序列,问最少要几下才能全部消除. 自然想到dp[i][j]表示序列i...j全部消除的最少操作数 有几种消除的方式都能通过枚举k(i<=k ...

随机推荐

  1. kali Linux下wifi密码安全测试(1)虚拟机下usb无线网卡的挂载 【转】

    转自:http://blog.chinaunix.net/uid-26349264-id-4455634.html 目录 kali Linux下wifi密码安全测试(1)虚拟机下usb无线网卡的挂载 ...

  2. eclipse自定义工具栏

    设置:1.Window2.Customize Perspective说明:Tool Bar Visibility定义菜单栏,Shortcuts定义右键new菜单

  3. 003_饿了么chaosmonkey实现

    背景 公司目前的服务设计大部分满足 design for failure 理念.随着业务复杂度的提升,我们很难再保证对系统故障的容错性.我们需要工具来验证服务的容错性,基于这个需求我们使用了 tc 工 ...

  4. 转载:编译安装Nginx(1.5.1)《深入理解Nginx》(陶辉)

    原文:https://book.2cto.com/201304/19618.html 1.5 configure详解 可以看出,configure命令至关重要,下文将详细介绍如何使用configure ...

  5. Java用四种方法实现阶乘n! (factorial)

    1. 引言 实现阶乘的方法很多,这边介绍四种方法,分别是递归,尾递归,循环和BigDecimal. 2. 代码 public class Test { public static void main( ...

  6. 基于python的k-s值计算

    做评分卡模型时(假设有多个自变量,因变量即是否违约.)通常需要筛选变量. k-s值的作用类似于AUC,它期初是用来评价模型(变量)对是否违约事件的区分程度的. # -*- coding: utf-8 ...

  7. Pandas详解一

    pandas简介 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具.pandas提 ...

  8. C++ code:for loop designs

    1  用for循环编出系列图形 该图形一共10行,每一行增加一个字符,所以应循环10次,每次输出一行.其循环模式为: :i<=;++i) { 输出第i行 换行 } 我们注意到,每一行长度的变化正 ...

  9. poj3666 线性dp

    要把一个序列变成一个不严格的单调序列,求最小费用 /* 首先可以证明最优解序列中的所有值都能在原序列中找到 以不严格单增序列为例, a序列为原序列,b序列为升序排序后的序列 dp[i][j]表示处理到 ...

  10. python+selenium九:ddt数据驱动

    第一种,测试数据放在Excel里面 test_Login: import unittestimport timeimport ddtimport osfrom selenium import webd ...