首页 > 其他分享 >CF1798E Multitest Generator 题解

CF1798E Multitest Generator 题解

时间:2023-08-22 09:55:17浏览次数:36  
标签:Generator 更改 后缀 题解 valueType texttt 序列 test CF1798E

题意

定义一个序列 \(b_1, b_2, b_3, \cdots, b_m\) 为 \(\texttt{test}\) 当且仅当 \(b_1 = m - 1\)。

定义一个序列 \(b_1, b_2, b_3, \cdots, b_m\) 为 \(\texttt{multitest}\) 当且仅当该序列可以划分为 \(b_1\) 段子串,且每段子串均为一个 \(\texttt{test}\)。

现给定一个长度为 \(n\) 的正整数序列 \(a_1, a_2, a_3, \cdots, a_n\),对于所有的 \(i \in \left[1, n\right)\),求出使原序列的后缀 \(a_i, a_{i + 1}, \cdots, a_n\) 为 \(\texttt{multitest}\) 的最小修改次数(每次修改可以更改一个元素,不可以删减元素)。

(\(1 \le n \le 3 \times 10^5\))。

题解

首先考虑一个性质

对于任意序列,均可以通过 \(2\) 次更改使其成为 \(\texttt{multitest}\)。

假设我们有任意序列 \(b_1, b_2, b_3, \cdots, b_m\),执行操作 \(b_1 \leftarrow 1, b_2 \leftarrow m - 2\) 即可使其成为 \(\texttt{multitest}\)。

那么我们只需要考虑当前序列能否通过小于 \(2\) 次操作使其变为 \(\texttt{multitest}\)。

首先考虑 \(0\) 次操作,即当前序列原始就是一个 \(\texttt{multitest}\)。

记 \(f_i\) 表示 \(i\) 的后缀能构成的连续合法 \(\texttt{test}\) 的个数,可以得出转移方程如下:

\[f_i = \begin{cases} 1 & i + a_i + 1 = n + 1 \\ 0 & i + a_i + 1 > n + 1 \lor f_{i + a_i + 1} = 0\\ f_{i + a_i + 1} + 1 & \text{otherwise} \end{cases}\]

可以发现 \(f\) 的值可以 \(\mathcal{O}(n)\) 求出。第 \(i\) 位的答案为 \(0\) 的充要条件为 \(f_{i + 1} = a_i\)。

接下来考虑 \(1\) 次操作,如果 \(i + 1\) 的后缀可以形成合法的若干 \(\texttt{test}\) 即 \(f_{i + 1} > 0\),那么直接执行更改 \(a_i \leftarrow f_{i + 1}\) 即可。

如果 \(i + 1\) 的后缀无法形成合法的 \(\texttt{test}\),那么考虑在该后缀中进行更改。可以发现一个性质

如果一个序列可以通过 \(1\) 次更改形成 \(k\) 个合法 \(\texttt{test}\),那么其一定可以通过 \(1\) 次更改形成 \(k^{\prime} \le k\) 个 \(\texttt{test}\)。

考虑改变原始更改方案。设在该方案中改变了 \(a_t\) 的值,在此之后的若干 \(\texttt{test}\) 的首位元素下标为 \(c_1, c_2, \cdots\),其中 \(a_t = c_0\),那么我们只需要执行 \(a_t \leftarrow c_{k - k^{\prime}} - 1\) 即可。若在此之后的 \(\texttt{test}\) 数量小于 \(k - k^{\prime}\),那么我们更改从后往前数第 \(k - k^{\prime} + 1\) 个 \(\texttt{test}\) 的首位元素即可。

所以我们只需要求出在 \(i\) 的后缀中通过 \(1\) 次更改可以形成的最多合法 \(\texttt{test}\) 数量 \(g_i\) 即可判定。若 \(a_i \le g_{i + 1}\),那么结合上文性质可得第 \(i\) 位的答案为 \(1\)。

下面考虑如何求出 \(g_i\) 的值,考虑两种转移

  • 改变 \(a_i\) 的值,那么因为可以任意更改当前 \(\texttt{test}\) 的长度即下一个 \(\texttt{test}\) 的首位元素且之后不能再次执行更改,所以在所有的可能首位元素中取 \(f\) 最大值即可,此时 \(\displaystyle g_i = \max\limits_{j = i + 1}^{n + 1} f_{j} + 1\);
  • 不改变 \(a_i\) 的值,那么下一个 \(\texttt{test}\) 的首位元素为 \(i + a_i + 1\),且之后可以进行更改,故从 \(g_{i + a_i + 1}\) 转移即可,即 \(g_i = g_{i + a_i + 1}\)。

两种情况取最大值即可推出 \(g_i\) 的值,利用后缀最大值优化即可以 \(\mathcal{O}(n)\) 的复杂度处理 \(f, g\) 两个数组的值。

Code

//Codeforces - 1798E
#include <bits/stdc++.h>

typedef int valueType;
typedef std::vector<valueType> ValueVector;

constexpr valueType MIN = INT_MIN >> 2;

int main() {
    valueType T;

    std::cin >> T;

    for (valueType testcase = 0; testcase < T; ++testcase) {
        valueType N;

        std::cin >> N;

        ValueVector source(N + 2), next(N + 2, N + 2), F(N + 2, MIN), G(N + 2, MIN), maxF(N + 2, MIN);

        for (valueType i = 1; i <= N; ++i) {
            std::cin >> source[i];
            next[i] = i + source[i] + 1;
        }

        maxF[N + 1] = F[N + 1] = G[N + 1] = 0;

        for (valueType i = N; i > 1; --i) {
            if (next[i] <= N + 1)
                F[i] = F[next[i]] + 1;

            G[i] = maxF[i + 1] + 1;

            if (next[i] <= N + 1)
                G[i] = std::max({G[i], G[next[i]] + 1});

            maxF[i] = std::max(maxF[i + 1], F[i]);
        }

        for (valueType i = 1; i < N; ++i) {
            if (source[i] == F[i + 1]) {
                std::cout << 0 << ' ';
            } else if (F[i + 1] > 0 || G[i + 1] >= source[i]) {
                std::cout << 1 << ' ';
            } else {
                std::cout << 2 << ' ';
            }
        }

        std::cout << '\n';
    }

    std::cout << std::flush;

    return 0;
}

标签:Generator,更改,后缀,题解,valueType,texttt,序列,test,CF1798E
From: https://www.cnblogs.com/User-Unauthorized/p/solution-CF1798E.html

相关文章

  • nginx: 405 not allowed问题解决
    问题背景:第三方跳转我方一个静态页面,该页面在浏览器地址栏输入url链接后可以直接访问,但对方系统跳转时nginx报405 notallowed原因:前后端分离项目,前端采用nginx部署,nginx默认配置是不支持post请求静态资源的,而对方跳转时采用的post请求,所以nginx拦截报405解......
  • Interval GCD 题解 || WHK废物快乐题
    题意给定一个序列,需要对其进行区间加和和查询\(\gcd\)操作。思路首先看到了区间加和,自然想到是直接打懒标记,但是呢。。。\(\gcd\)具有一些特殊性,我们并不能通过向下传递标记的方式维护\(\gcd\)。于是想到昨天Tad讲树状数组区间修改的差分数组方案。我们创建一个数组......
  • 2023 年山东省大学生程序设计竞赛 个人题解
    比赛链接现场赛榜单洛谷重现赛重现赛个人下饭操作太多,后程直接开摆,分数不够理想。这比赛严格来说应该比区域赛简单。不过有几题我挺喜欢的。先发出来,C、D、F、H、J题这几天会填坑。A.Orders点击查看题意简述某工厂收到\(n\)个订单,每个订单形如「在第\(a_i\)天前交......
  • 「NOIP2013」货车运输 题解
    「NOIP2013」货车运输前言这道题算是一个稍有思维难度的MST+LCA题目了。稍微卡了一会(0-88-88-88-100(打表)-100(打表)-100(正解)),开始是打了表过了,后面在DCZ的帮助下正解通过(下面注释提到的一个坑)。题目大意给出一张无向图\(G\),有\(n\)个点和\(m\)个边\((x,y)=z\),找到一......
  • 猴王 题解 || 冷门的 pb_ds 库
    猴王前言虽然很久以前(6月)在我们学并查集的时候QYC就给我们讲了左偏树可以拿来做这道题,但是左偏树作为拓展内容还是稍有难度,最近在gcc中看到pb_ds库,发现非常好用,于是就有了这种偷懒解法。pb_ds库pb_ds库是内置于GCC中的一种拓展标准库,可以在CCF系列比赛中使用。pb......
  • 「NOIP2017 普及组」棋盘 题解
    前言一个绿题,风光啊QwQ题面传送门思路怎么走我们定义一个函数dfs(x,y,coin,can,color)x,y表示坐标,coin表示当前的金币数量,color表示当前坐标的颜色,can表示当前是否能施展魔法。再加一个mp数组记录颜色,-1表示无颜色,0表示红色,1表示黄色为什么不直接使用mp[x][y]获取颜......
  • [CF1790F] Timofey and Black-White Tree 题解
    [CF1790F]TimofeyandBlack-WhiteTree题解题目描述ZYH有一棵\(n\)个节点的树,最初\(c_0\)号节点是黑色,其余均为白色。给定操作序列\(c_1,c_2,\cdots,c_{n-1}\),第\(i\)次操作表示将\(c_i\)号节点染黑。每次操作后,输出距离最近的两个黑点间的距离。两点\(u,v\)间......
  • CF1762E Tree Sum 题解
    题意对于一棵\(n\)个节点的树\(T\),定义\(\operatorname{good}(T)\)为真当且仅当边权\(w\in\left\{-1,1\right\}\)且对于任意节点\(u\),均有\(\displaystylef(u)=\prod\limits_{\left(u,v\right)\inE}w\left(u,v\right)=-1\)。求\[\sum\limits_{\operat......
  • RTSP/Onvif视频服务器EasyNVR安防视频云服务调用接口录像会被自动删除的问题解决方案
    EasyNVR安防视频云服务是基于RTSP/Onvif协议接入的视频平台,可支持将接入的视频流进行全平台、全终端的分发,分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等。平台丰富灵活的视频能力,可应用在智慧校园、智慧工厂、智慧水利等场景中。有用户反馈,在使用EasyNVR接入设备......
  • [ABC315G] Ai + Bj + Ck = X (1 <= i, j, k <= N) 题解
    [ABC315G]Ai+Bj+Ck=X(1<=i,j,k<=N)题解题目描述求题目中式子的数量。思路因为\(N\le10^6\),所以考虑枚举\(k\),那么变为求\(ai+bj=x-ck,i,j\in[1,N]\),这个问题可以通过Exgcd算法求解。首先考虑求出一组\(i,j\)的特解\(x',y'\),根据通解\(x=x'+......