嘟嘟嘟

这题刚开始是什么思路也没有,关键是不知道怎么解决序列反转的问题。

然后我就想到如果暴力反转一个序列的话,实际上就是不断交换数组中的两个数ai和aj,同时要满足交换的数不能交叉。

然后又看了一眼(岂止一眼)题解,因为ai <= 50,所以令dp[i][j][L][R]表示区间[i, j],min(ak) >= L, max(ak) <= R时,反转一次的最长不下降子序列。

显然是一个区间dp,那么[i, j]可以从[i + 1, j],[i, j - 1]或是[i + 1, j - 1]转移过来,所以L,R也只可能从ai+1,aj-1转移过来。然后还要考虑交换或者不交换的情况。代码就是dp式了,这里就不写了

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch)) {ans = ans * + ch - ''; ch = getchar();}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) x = -x, putchar('-');
if(x >= ) write(x / );
putchar(x % + '');
} int n, a[maxn];
int dp[maxn][maxn][maxn][maxn]; int main()
{
n = read();
for(int i = ; i <= n; ++i) a[i] = read(), dp[i][i][a[i]][a[i]] = ;
for(int len = ; len <= n; ++len)
for(int i = ; i + len - <= n; ++i)
{
int j = i + len - ;
for(int l = ; l <= ; ++l)
for(int L = ; L + l - <= ; ++L)
{
int R = L + l - ;
dp[i][j][L][R] = max(dp[i][j][L][R], max(dp[i + ][j][L][R], dp[i][j - ][L][R]));
dp[i][j][L][R] = max(dp[i][j][L][R], max(dp[i][j][L + ][R], dp[i][j][L][R - ]));
dp[i][j][min(L, a[i])][R] = max(dp[i][j][min(L, a[i])][R], dp[i + ][j][L][R] + (a[i] <= L));
dp[i][j][L][max(R, a[j])] = max(dp[i][j][L][max(R, a[j])], dp[i][j - ][L][R] + (a[j] >= R));
dp[i][j][min(L, a[j])][R] = max(dp[i][j][min(L, a[j])][R], dp[i + ][j - ][L][R] + (a[j] <= L)); //一下三行是ai和aj交换
dp[i][j][L][max(R, a[i])] = max(dp[i][j][L][max(R, a[i])], dp[i + ][j - ][L][R] + (a[i] >= R));
dp[i][j][min(L, a[j])][max(R, a[i])] = max(dp[i][j][min(L, a[j])][max(R, a[i])], dp[i + ][j - ][L][R] + (a[i] >= R) + (a[j] <= L));
}
}
write(dp[][n][][]), enter;
return ;
}

[USACO17JAN]Subsequence Reversal的更多相关文章

  1. [USACO17JAN]Subsequence Reversal序列反转

    题目描述 Farmer John is arranging his NN cows in a line to take a photo (1 \leq N \leq 501≤N≤50). The he ...

  2. [USACO17JAN] Subsequence Reversal序列反转 (dfs+记忆化)

    题目大意:给你一个序列,你可以翻转任意一段子序列一次,求最长不下降子序列长度 tips:子序列可以不连续,但不能破坏在原序列中的顺序 观察数据范围,n<=50,很小,考虑dfs *dfs来跑区间 ...

  3. bzoj4758: [Usaco2017 Jan]Subsequence Reversal(区间dp)

    4758: [Usaco2017 Jan]Subsequence Reversal Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 76  Solved ...

  4. USACO 2017 January Platinum

    因为之前忘做了,赶紧补上. T1.Promotion Counting 题目大意:给定一个以1为根的N个节点的树(N<=100,000),每个节点有一个权值,对于每个节点求出权值比它大的子孙的个 ...

  5. 区间dp提升复习

    区间\(dp\)提升复习 不得不说这波题真的不简单... 技巧总结: 1.有时候转移可以利用背包累和 2.如果遇到类似区间添加限制的题可以直接把限制扔在区间上,每次只考虑\([l,r]\)被\([i, ...

  6. [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  7. [LeetCode] Is Subsequence 是子序列

    Given a string s and a string t, check if s is subsequence of t. You may assume that there is only l ...

  8. [LeetCode] Wiggle Subsequence 摆动子序列

    A sequence of numbers is called a wiggle sequence if the differences between successive numbers stri ...

  9. [LeetCode] Increasing Triplet Subsequence 递增的三元子序列

    Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the ar ...

随机推荐

  1. sqlplus连接oracle语法

    sqlplus文件在product\11.2.0\dbhome_1\BIN目录下. 连接语法:用户名/密码@ip/服务名

  2. TOJ 2888 Pearls

    Description In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces ...

  3. TOJ 4119 Split Equally

    描述 Two companies cooperatively develop a project, but they don’t like working with one another. In o ...

  4. 支付宝小程序与微信小程序开发功能和语法糖不同

    最近开始负责公司webapp数据打通支付宝小程序,之前已经打通了微信小程序,现在根据支付宝小程序的开发文档在之前的模板上面做修改. 在修改模板的过程中,总结一下双方功能和语法糖的不同之处. 框架: a ...

  5. 线程中断方法interrupt() 与 cancel()

    (一).关于interrupt()     interrupt()并不直接中断线程,而是设定一个中断标识,然后由程序进行中断检查,确定是否中断.     1. sleep() & interr ...

  6. tushare获取的数据与mysql数据库交互简单范例

    #!/usr/bin/python2.7# -*- coding: UTF-8 -*- import tushare as tsimport pandas as pdfrom sqlalchemy i ...

  7. Canvas知识点汇总

    本文主要记录Canvas基础知识汇总. 1.Canvas定义 <canvas> 元素是HTML5中的新元素,通过它可以在网页中绘制出所需的图形.<canvas>标签只是图形的容 ...

  8. String变量的两种创建方式

    在java中,有两种创建String类型变量的方式: String str01="abc";//第一种方式 String str02=new String("abc&qu ...

  9. css样式学习小知识

    1. 使用百分比设置宽高 自适用宽高的,有分割的区域,可以适用百分比:30% 70% 如果有一部分是固定的宽度或者高度,可以使用:height: calc( 100% - 36px ); 2. inp ...

  10. es6新语法的使用

    1.声明变量: let 声明变量 作用域代码块作用域{} 尽在模块 先使用后声明 会报错 { let a= 12; alert(a) } let 不允许重复声明同一个变量 const 声明是一个常量, ...