把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF1798E Multitest Generator 分析

题目概述

定义一个 test 为一个长 \(n+1\) 的序列且第 \(1\) 项是 \(n\)

定义一个 multitest 为满足如下条件的序列:

\(n−1\) 项可以划分为 \(m\) 个 test。
\(1\) 项为 \(m\)
给定一个序列 \(a\),你需要对于 \(a\) 的每个长度大于 \(2\) 的后缀求出最少修改多少个数使得该后缀满足是一个 multitest。

$∑n≤3×10 $

分析

发现答案只有 \(0,1,2\)(自己思考一下)。

\(f_{i,0/1}\) 表示后 \(i\) 个删了 \(0/1\) 所得到的最多区间(更多的不劣于更少的)

然后分类讨论即可。

代码

时间复杂度 \(\mathcal{O}(\sum n)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#define int long long
#define N 300005
using namespace std;
int n,a[N],T,f[N][2],ans[N];
signed main(){
    cin >> T;
    for (;T--;) {
        // for (int i = 0;i <= n + 1;i ++) f[i][0] = f[i][1] = -1e18;
        scanf("%lld",&n);
        for (int i = 1;i <= n;i ++) scanf("%lld",&a[i]),f[i][0] = f[i][1] = -1e18;
        f[n + 1][1] = -1e18;
        f[n + 1][0] = 0;
        int mx = 0;
        for (int i = n;i;i --) {
            f[i][1] = mx + 1;
            if (i + a[i] + 1 <= n + 1) {
                f[i][1] = max(f[i][1],f[i + a[i] + 1][1] + 1);
                f[i][0] = f[i + a[i] + 1][0] + 1;
            }
            mx = max(mx,f[i][0]);
            if (a[i - 1] == f[i][0]) ans[i - 1] = 0;
            else if (f[i][0] >= 1 || a[i - 1] <= f[i][1]) ans[i - 1] = 1;
            else ans[i - 1] = 2;
        }
        for (int i = 1;i < n;i ++) printf("%lld ",ans[i]);
        putchar('\n');
    }
    return 0;
}
posted @ 2025-10-13 11:45  high_skyy  阅读(6)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end