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;
}

浙公网安备 33010602011771号