题解:P12687 [KOI 2022 Round 1] 鹅卵石
lailai0916 · · 题解
题意简述
给定长度为
解题思路
-
枚举每个起点
i ,向右模拟交替相邻配对:维护一个变量t ,初始为a_i ,然后依次计算t=a_j-t 。 -
若
t>0 且恰好等于a_{j+1} ,则区间[i,j+1] 可以完全通过相邻配对消除,记录其右端点为j 。否则若t\le 0 则跳出,尝试下一个起点。 -
令
f_i 表示在位置[1,i+1] 范围内,最多能选的互不重叠“可消除区间”数量。 -
对每个右端点
i ,先继承f_{i-1} (不选任何以i 结尾的区间),再遍历所有以i 为右端的合法起点u ,计算其对应候选值f_{u-2}+1 (若u=1 则为1 ),取最大更新f_i 。 -
最大可配对消除区间数为
f_{n-1} ,剩下必须单点拿的次数即n-f_{n-1} 。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N=2505;
int a[N],f[N];
vector<int> G[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<n;i++)
{
int t=a[i];
for(int j=i;j<n;j++)
{
if(j>i)t=a[j]-t;
if(t<=0)break;
if(t==a[j+1])G[j].push_back(i);
}
}
for(int i=1;i<n;i++)
{
f[i]=f[i-1];
for(auto u:G[i])
{
f[i]=max(f[i],u==1?1:f[u-2]+1);
}
}
cout<<n-f[n-1]<<'\n';
return 0;
}