首页 > 其他分享 >01 交换串 题解

01 交换串 题解

时间:2024-10-02 11:00:31浏览次数:1  
标签:max 01 int 题解 tt 交换 ans

题意简述

给定一个长为 \(n\) 的 \(\tt 01\) 串 \(s\),你需要对 \(s\) 进行恰好 \(m\) 次交换,每次只能交换相邻的不同字符,最大化操作后 \(s\) 的价值。\(s\) 的价值被定义为,对于每一个 \(i\),记 \(1 \sim i - 1\) 中,和 \(s_i\) 不同的 \(s_j\) 有 \(l\) 个,\(r\) 同理,\(f(s_i, i, l, r)\) 的和就是 \(s\) 的价值。

对于原题,是最大化得到的串中子序列 \(\tt 0010\) 和 \(\tt 1101\) 的总数。其实,此时 \(f(s_i, i, l, r) = \dfrac{l(l-1)}{2} r\)。我们的 \(f\) 完全可以更复杂,比如加入 \((-1) ^ {s_i} v_i\) 的系数,\(l^{i - 1} r^{n - i}\) 等奇怪的东西。

\(n, m \leq 500\),保证 \(s\) 可以操作。

题目分析

首先,根据大名鼎鼎的「\(\tt 01\) 守恒定理」,\(\tt 01\) 不会凭空产生,也不会凭空消失,操作前后 \(s\) 中 \(0 / 1\) 的数量没有发生变化。

我们进而发现,我们只会交换不同的字符,那么相同的字符之间的相对位置关系也是确定了的。这样,我们可以计算到达最终的字符串需要进行多少步,就是每一个 \(0\) 或每一个 \(1\),对应后位置之差绝对值之和。

我们考虑 DP,记 \(f'_{i, j, k}\) 表示最终字符串,已经决策前 \(i\) 位,前 \(i\) 位中有 \(j\) 个 \(0\),\(i - j\) 个 \(1\),\(0\) 的位置之差绝对值之和为 \(k\),的 \(\max \sum f\)。转移时,按照 \(s_i = 0 / 1\) 分类转移即可。其实分析到这里,代码就很好敲了。

记 \(0 / 1\) 出现次数为 \(c_{0 / 1}\),原串中每个 \(1\) 出现的位置序列为 \(p\),转移方程:

\[\begin{aligned} \large f'_{i + 1,\ j,\ k} &\gets f'_{i,\ j,\ k} + f(1, i + 1, j, c_0 - j) \\ \large f'_{i + 1,\ j + 1,\ k + \vert p_{j + 1} - (i + 1) \vert} &\gets f'_{i,\ j,\ k} + f(0, i + 1, i - j, c_1 - (i - j)) \end{aligned} \]

其中 \(a \gets b\) 表示 \(a = \max \{ a, b \}\)。

最终答案是 \(f'_{n,\ c_0,\ m}\) 吗?我们可以交换两次相邻不同的位置,浪费 \(2k\) 次操作,所以答案为 \(\max \limits _ {k = 0} ^ {\left\lfloor \dfrac{m}{2} \right\rfloor} f'_{n,\ c_0,\ m - 2k}\)。

代码

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

const int N = 520;

int n, m;
char str[N];

int $0[N], $1;
int f[2][N][N], ans;
inline void tomax(int &a, int b) { b > a && (a = b); }

signed main() {
    #ifndef XuYueming
    freopen("b6e6.in", "r", stdin);
    freopen("b6e6.out", "w", stdout);
    #endif
    scanf("%s%d", str + 1, &m);
    for (; str[n + 1]; ++n);
    for (int i = 1; i <= n; ++i) {
        if (str[i] == '0') $0[++*$0] = i;
        else ++$1;
    }
    memset(f[0], 0xff, sizeof (f[0]));
    f[0][0][0] = 0;
    for (int i = 0, t; i <= n - 1; ++i) {
        memset(f[(i + 1) & 1], 0xff, sizeof (f[(i + 1) & 1]));
        for (int j = max(0, i - $1); j <= i && j <= *$0; ++j)
        for (int k = 0; k <= m; ++k)
            if (~f[i & 1][j][k]) {
                tomax(f[(i + 1) & 1][j][k], f[i & 1][j][k] + (j * (j - 1) >> 1) * (*$0 - j));
                if (j == *$0) continue;
                t = k + abs($0[j + 1] - i - 1);
                if (t <= m)
                    tomax(f[(i + 1) & 1][j + 1][t], f[i & 1][j][k] + ((i - j) * (i - j - 1) >> 1) * ($1 - (i - j)));
            }
    }
    for (int i = m; i >= 0; i -= 2)
        ans = max(ans, f[n & 1][*$0][i]);
    printf("%d", ans);
    return 0;
}

标签:max,01,int,题解,tt,交换,ans
From: https://www.cnblogs.com/XuYueming/p/18444469

相关文章

  • CSP-S/NOIP提高组 真题题解总结
    DP:线性dpP1091[NOIP2004提高组]合唱队形比较简单的一道题。求出以\(i\)结尾的最长上升子序列和以\(i\)为头的最长下降子序列,相加\(-1\)即可。P1052[NOIP2005提高组]过河如果不考虑\(L\)的范围,那么就是一道简单的线性dp。但是\(L\)很大,石头数量很少,......
  • 区间 题解
    题意简述求长度为\(n\)的序列\(a\)的最长连续子序列\([l,r]\),满足\(\existsi\in[l,r],\gcd(a_l,\ldots,a_r)=a_i\)。\(1\leqn\leq4\times10^6\),\(1\leqa_i\leq10^{18}\)。题目分析根据\(\gcd(a,b)=a\)等价于\(b\bmoda=0\),这个区间的限......
  • JOI 2018 Final
    A-ストーブ(Stove)有\(n\)个客人将要来访,第\(i\)个客人的来访时间为\([a_i,a_i+1]\),保证\(\foralli\in[1,n),a_i<a_{i+1}\)。在每个客人来访时,你都需要保证暖炉是亮着的(初始时暖炉为熄灭状态)。你可以在任意时刻熄灭暖炉,但每次点亮都需要消耗一根火柴,且你......
  • 题解 P2726 【[SHOI2005]树的双中心】
    首先,我们会有一个很简单的想法,枚举断边,产生两棵子树,然后在两棵树内分别求带权重心,计算贡献,这样的话复杂度是\(O(n^2)\)的。那么我们要好好利用$h\leq100$的性质。考虑\(sze[u]\)为带权重量,\(g[u]\)为以\(u\)为根的树,所有点都到\(u\)的代价。所以\(g[u]=\sum\l......
  • AT_abc373_e 的题解
    (一)二分套二分。(感觉是一个很麻烦的做法。)题目问的是让额外给的票最少,考虑二分答案。设二分的答案为\(x\),该候选人原来的得票为\(v\),想要超过他至少要\(x+v+1\)。同时用前缀和维护区间和。第一种情况为该候选人在前\(m\)个人中,如下图所示。绿色箭头为被讨论的人,蓝色箭......
  • 优美函数 题解
    题意简述给你函数\(f\):\[f(x,y,u)=\left\{\begin{array}{rcl}u-y,&x=1\\u,&1<x\ley,\\gcd(x,y)=1\\-x\cdoty,&x\neq1,\\gcd(x,y)=x\\0,&\text{otherwise}.\end{array}\right.\]对于一个长度为\(n\)的序列......
  • ABC 模拟赛 | A Passing Contest 001题解记录(A,B,C,D)
    比赛链接https://www.luogu.com.cn/contest/126344[APC001]A-CT不必多说,多次取模#include<iostream>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<deque>#include<math.h>#include<map>......
  • Codeforces2014E Rendez-vous de Marian et Robin(分层图最短路)
    题意给定一个无向图,含有\(n\)个点和\(m\)条边。题解点击查看代码#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;constexpri64inf=1e18;voidsolve(){intn,m,h;cin>>n>>m>>h;vector<vector<......
  • 01_Elasticsearch顶尖高手系列课程的介绍
    3、课程内容介绍(1)核心知识篇课程特点(1)使用最新Elasticsearch5.2版本讲解,市面上的书籍和视频几乎都停留在2.x版本(2)深入浅出ES核心工作原理,全部手工画图讲解,完全不同于市面上已有视频的PPT讲解(3)涵盖Elasticsearch所有核心知识点,系统化,体系完整详细,有一定深度,包括完整Java开发......
  • CF1214G Feeling Good 题解
    题目链接点击打开链接题目解法我真菜啊,感觉每一步都不难,但一步都没想到/yun考虑两行\(x,y\)什么时候可以构造出合法的矩形?即\(x\)中需要有\(y\)对应位置为\(0\)的\(1\),\(y\)中需要有\(x\)对应位置为\(0\)的\(1\)归纳一下,\(x\)不是\(y\)的子集且\(y\)不......