首页 > 其他分享 >CF1527E, Partition Game

CF1527E, Partition Game

时间:2023-05-11 13:00:36浏览次数:32  
标签:last min Partition CF1527E segtr Game cost fk dp

题意

定义一个数组的 \(cost\) 为数组中出现过的每个元素的最后一个位置减第一个位置。

\[cost(array) = \sum_{x\in set(array)}last(x) - first(x) \]

给定一个 \(N\) 个数的数组 \(A\),将其分为 \(K\) 段,求最小 \(cost\)。

题解

设 \(dp_{i, j}\) 为前 \(i\) 个数分为 \(j\) 段的最小 \(cost\)。

状态转移:枚举 \(k\), 表示将区间 \([1, k]\) 分为 \(j - 1\)段,最后还有一段 \([k + 1, i]\)。

\[dp_{i, j} = \min_{k=j-1}^{i-1} (dp_{k, j-1} + cost(k + 1, i)) \]

for j in [1, K + 1)
    for i in [j, N + 1)
        for k in [j - 1, i)
            dp[i][j] = min(dp[i][j], dp[k][j - 1] + cost(k + 1, i))

复杂度为 \(N ^ 2 K\),考虑使用数据结构优化。

发现线段树能维护区间 \(\min\),则设 \(f_{i, j, k} = dp_{k, j-1} + cost(k + 1, i)\),令线段树维护对于当前 \(j, i\) 所需要的 \(f_k\) 。

\[dp_{i, j} = \min_{k=j-1}^{i-1} (f_{i, j, k}) \]

for j in [1, K + 1)
    for i in [j, N + 1)
        dp[i][j] = segtr_fk.min(j - 1, i - 1)

假设当遍历到 \(j, i - 1\) 时,线段树维护着正确的信息,在由 \(i-1\) 到 \(i\) 时,应如何更新线段树:

\[f_k = dp_{k, j - 1} + cost(k + 1, i - 1) + dist(last_{a_i}, cur_{a_i}) \]

发现对于 \(k < last_{a_i}\) 的 \(f_k\),\(A_i\) 不是最后一段区间的第一次出现,所以 \(f_k\) 要加上 \(dist(last_{a_i}, cur_{a_i})\)。

而对于 \(k \geq last_{a_i}\) 的 \(f_k\),\(A_i\) 是最后一段区间的第一次出现,\(f_k\) 不变。

for j in [1, K + 1)
    for i in [j, N + 1)
        segtr_fk.add(1, last[i], i - last[i])
        dp[i][j] = segtr_fk.min(j - 1, i - 1)

发现每层的 \(f_k\) 都由 \(dp_{k, j - 1}\) 为初值,在遍历 \(i\) 时加上 \(dist\) 更新。因此当从第 \(j - 1\) 层到第 \(j\) 层时,\(f\) 应初始化为 \(dp_{j-1}\)。

for j in [1, K + 1)
    segtr_fk.build(dp[][j-1])
    for i in [j, N + 1)
        segtr_fk.add(1, last[i], i - last[i])
        dp[i][j] = segtr_fk.min(j - 1, i - 1)

代码

void solve()
{
    int N, K;
    std::cin >> N >> K;

    std::vector<int> A(N + 1);
    std::vector<int> pre(N + 1);
    std::vector<int> last(N + 1);
    for (int i = 1; i <= N; i++)
    {
        std::cin >> A[i];

        last[i]   = pre[A[i]];
        pre[A[i]] = i;
    }

    std::vector<i64> dp(N + 1);
    // 初始化 j = 1
    for (int i = 1; i <= N; i++)
    {
        dp[i] = dp[i - 1];
        if (last[i])
        {
            dp[i] += i - last[i];
        }
    }

    for (int j = 2; j <= K; j++)
    {
        LazySegmentTree<i64, op, e, i64, mp, comp, id> f(dp);
        for (int i = j; i <= N; i++)
        {
            if (last[i])
            {
                f.apply(1, last[i], i - last[i]);
            }
            dp[i] = f.prod(j - 1, i);
        }
    }

    std::cout << dp[N] << '\n';
}

标签:last,min,Partition,CF1527E,segtr,Game,cost,fk,dp
From: https://www.cnblogs.com/yHan234/p/17390745.html

相关文章

  • GAMES101 VS2019 2022环境配置
    GAMES101VS20192022环境配置Eigen库的配置在官网https://eigen.tuxfamily.org/index.php?title=Main_Page中下载Eigen库的zip格式。将压缩包解压为eigen3同时解压到指定路径,我这里为D:\include\eigen3。使用VS2019创建一个空项目,将代码框架的头文件和源文件加入到项......
  • [HGAME 2022 week1]easyasm
    查壳:64位,进IDA:好家伙,不给看伪代码,来吧汇编走起:设置两个段,一个数据段(dseg),一个额外段(seg001)看看吧,dseg段中的内容'hgame{Fill_in_your_flag}'seg001段中的内容:(不想说话)关键:逐个分析吧,首先是将ax清零,然后从数据段中拿出数据,向左偏移4,压入栈中,再清零ax,再从数据段中拿出......
  • AIGC生产工艺流程之games生产流程
    AIGC生产工艺流程中的“games生产流程”主要是指游戏的生产过程。一般来说,游戏生产流程包括游戏设计、策划、程序开发、美术制作、音效制作等等环节,具体流程可以根据不同公司和项目有所差异。其中游戏设计一般是一个较为重要的环节,主要确定游戏的整体架构和玩法规则;策划环节是根据......
  • Codeforces 280C Game on Tree
    设\(p_i\)为\(i\)涂色或不涂色,\(1\)为涂,\(0\)为不涂,答案即为\(E[\sum_{i=1}^np_i]\)然后转化一下柿子:\(\sum_{i=1}^nE[p_i]\),这就很好求了,单独求每个点\(E[p_i]\)的值就行了考虑对于\(u\)点,\(p_u=1\),即能被涂需要满足其祖先都比其晚涂色假设现在有一个序列里面......
  • AtCoder Regular Contest 122 D XOR Game
    洛谷传送门AtCoder传送门从高到低按位考虑。设当前位有\(k\)个\(1\)。如果\(k\bmod2=0\),这意味着Alice如果选了一个数,Bob可以选相同的数。发现可以分成\((0,0),(1,1)\)两组,递归下去即可。如果\(k\bmod2=1\),意味着答案这一位一定是\(1\)(因为无论如何都不......
  • J - Simple Game (博弈论外壳下的模运算考察题目)
    原题链接:https://vjudge.net/contest/555710#problem/J手工翻译:Alice和Bob在玩一个游戏有这样一个数列a1,a2,a3,a4……an长度为n,他们轮流移走一个整数当数列中没有可移走的整数时游戏结束,Alice移走的数的和是S1,Bob移走的数的和是S2如果abs(s1-s2)为奇数,Alice赢,否则Bob赢接下来给......
  • AtCoder Regular Contest 116 F Deque Game
    洛谷传送门AtCoder传送门很强的博弈+性质题。下文令A为Takahashi,B为Aoki。发现单独考虑一个序列\(a_1,a_2,...,a_n\):若\(n\bmod2=0\):若A为先手,答案为\(\max(a_{\frac{n}{2}},a_{\frac{n}{2}+1})\);若B为先手,答案为\(\min(a_{\frac{n}{2}},a_{\frac......
  • Game Engine Architecture(游戏引擎架构)
    推荐序1最初拿到《GameEngineArchitecture》一书的英文版,是编辑侠少邮寄给我的打印版。他建议我接下翻译此书的合同。当时我正在杭州带领一个团队开发3D游戏引擎,我和我的同事都对这本书的内容颇有兴趣,两大本打印的英文书立刻在同事间传开。可惜那段时间个人精力顾及不来,把近千页......
  • Python partition使用技巧
    partition()方法用来根据指定的分隔符将字符串进行分割。如果字符串包含指定的分隔符,则返回一个3元的元组,第一个为分隔符左边的子串,第二个为分隔符本身,第三个为分隔符右边的子串。flask源代码的run模块中,出现的代码当做示例defrun():......_host='127.0.0.1'......
  • 题解:【CF235D】Graph Game
    题目链接根据期望的线性性,一次操作使得接下来要递归处理\(|G|\)个点,将这些贡献分摊到\(|G|\)个点上,这样我们接下来只需要计算概率。首先考虑如果是树怎么做。操作等价于随机一个排列,顺次删掉排列中的点,并求出删掉当前点之前其所处的连通块的大小。记当前\(x\)为点分治中心......