上海市计算机学会竞赛平台2025年1月月赛丙组分块序列
题目描述
Eve 有一个长度为 nn 的序列 a1∼na1∼n,他想对这个序列进行分块。
一个分块方案是合理的,当且仅当每一块都以这块的长度开头,这里的长度不包含首个元素。
例如 [3,1,2,3,2,1,2][3,1,2,3,2,1,2] 就是一个合理的分块方案,但 [3,1,2,2,1,2][3,1,2,2,1,2] 不是,因为第一块没有以其长度开头。
Eve 发现,并不是所有序列都能被合理地分块,比如 [1,4,3][1,4,3] 没有合理的分块方案,于是他转而想知道,如果可以对这个序列进行一些改动,能不能得到合法的分块方案呢?
请求出,最少从 aa 中删除多少元素,才能使得 aa 至少有一个合法的分块方案。
输入格式
第一行一个整数 TT 表示数据组数。
对于每组数据,第一行一个整数 nn 表示序列长度,第二行 nn 个整数 a1∼na1∼n 表示序列。
输出格式
对于每组数据,输出一行一个整数表示答案。
数据范围
对于 30%30% 的数据,1≤n,∑n≤201≤n,∑n≤20,1≤ai≤201≤ai≤20。
对于 60%60% 的数据,1≤n,∑n≤2×1051≤n,∑n≤2×105,1≤ai≤1001≤ai≤100。
对于 100%100% 的数据,1≤T≤1041≤T≤104,1≤n≤2×1051≤n≤2×105,1≤ai≤1061≤ai≤106,∑n≤2×105∑n≤2×105。
样例数据
输入:
7
7
3 3 4 5 2 6 1
4
5 6 3 2
6
3 4 1 6 7 7
3
1 4 3
5
1 2 3 4 5
5
1 2 3 1 2
5
4 5 5 1 5
输出:
0
4
1
1
2
1
0
详见代码:
#include<bits/stdc++.h>
using namespace std;
int a[200005];
int dp[200005];
int main()
{
int t, n;
cin >> t;
while(t--)
{
cin >> n;
memset(dp, 0x3f, sizeof(dp));
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
dp[0] = 0;
for(int i = 1; i <= n; i++)
{
dp[i] = min(dp[i], dp[i - 1] + 1);
if (a[i] + i <= n)
{
dp[a[i] + i] = min(dp[a[i] + i], dp[i - 1]);
}
}
cout << dp[n] << endl;
}
return 0;
}