Live2D

Solution -「ZJOI 2020」「洛谷 P6631」序列

Description

  Link.

  给定一个长为 n 的非负整数序列 an,你可以进行如下操作:

  • [l,r],将其中所有 a1
  • [l,r],将其中奇数下标的 a1
  • [l,r],将其中偶数下标的 a1

  求至少需要几次操作使得所有 a 值变为 0

  n105,数据组数 T10

Solution

  道路铺设永放光芒!

  记集族 I 包括所有一次操作可能涉及的下标集合,写出线规

minimize    z=PIxPs.t.{u, PuxPauu, PuxPauP, xP0

转对偶

maximize    z=u=1nau(sutu)s.t.{P, uP(suti)1u, su,tu0

  令 du=sutu,由第一个约束,显然有 du1;而为最大化 u=1naudu,可以得到 du{1,0,1}。那么就能简单 DP:令 f(i,x,y,z) 表示考虑了 d1..i,一类/二类/三类操作涉及的操作集合中,最大后缀 d 之和为 x/y/z ({0,1}),枚举 du=1,2,3 分别转移即可。

  复杂度 O(Tn)(其实带一个 logn24 倍常数 qwq)。

Code

/*~Rainybunny~*/

#include <cstdio>
#include <cstring>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )

typedef long long LL;

inline int rint() {
    int x = 0, f = 1, s = getchar();
    for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
    for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
    return x * f;
}

template<typename Tp>
inline void wint( Tp x ) {
    if ( x < 0 ) putchar( '-' ), x = -x;
    if ( 9 < x ) wint( x / 10 );
    putchar( x % 10 ^ '0' );
}

template<typename Tp>
inline void chkmax( Tp& a, const Tp& b ) { a < b && ( a = b, 0 ); }
inline int imax( const int a, const int b ) { return a < b ? b : a; }

const int MAXN = 1e5;
const LL LINF = 1ll << 60;
int n, a[MAXN + 5];
LL f[MAXN + 5][2][2][2];

int main() {
    for ( int T = rint(); T--; ) {
        n = rint();
        rep ( i, 1, n ) a[i] = rint();

        memset( f, 0xc0, sizeof f );
        f[0][0][0][0] = 0;
        rep ( i, 1, n ) rep ( w, -1, 1 ) {
            rep ( x, 0, 1 ) rep ( y, 0, 1 ) rep ( z, 0, 1 ) {
                if ( w + x <= 1 && w + ( i & 1 ? y : z ) <= 1 ) {
                    chkmax( f[i][imax( imax( w, w + x ), 0 )]
                      [i & 1 ? imax( imax( w, w + y ), 0 ) : y]
                      [i & 1 ? z : imax( imax( w, w + z ), 0 )],
                      f[i - 1][x][y][z] + w * a[i] );
                }
            }
        }

        LL ans = -LINF;
        rep ( x, 0, 1 ) rep ( y, 0, 1 ) rep ( z, 0, 1 ) {
            chkmax( ans, f[n][x][y][z] );
        }
        wint( ans ), putchar( '\n' );
    }
    return 0;
}

posted @   Rainybunny  阅读(69)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示