专栏文章

题解:AT_arc195_d [ARC195D] Swap and Erase

AT_arc195_d题解参与者 3已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@mipt1pqy
此快照首次捕获于
2025/12/03 17:28
3 个月前
此快照最后确认于
2025/12/03 17:28
3 个月前
查看原文
感性证明一下每个数最多只会被换一次的结论。
我们考虑怎样交换才是优的,举个栗子:
CPP
A B A B
显然交换中间的 AB 才是优的。
所以说我们得到一个结论:只有在交换后,22 操作的数量减两次及以上才会更优,但一次操作最多减两次,所以交换后,22 操作的数量减两次才会更优。
我们考虑对于同一个数,交换两次会发生什么。
那么就是说,你一共要减少四次 22 操作,才能使交换两次比交换两次以下更优。
但是我们又发现,你对于同一个数交换两次,最多只会影响三个数,也就是说最多只会减少三个 22 操作,所以显然是不优的。
那么交换两次已经是不优的了,那么交换两次以上也是不优的了。
所以每个数最多只会被交换一次。
如果有了这个结论,剩下的就很简单了。
fi,0/1f_{i,0/1} 表示对于序列 a1,a2,,aia_1,a_2,\dots,a_i,将 aia_iai1a_{i-1} 不换/换时,最少要几次操作才能将序列清空。
然后就可以列出 dp 方程:
{fi,0=min(fi1,0+[aiai1],fi1,1+[aiai2])fi,1=1+[aiai1]+min(fi2,0+[aiai2],fi2,1+[aiai3])\begin{cases} f_{i,0}=\min(f_{i-1,0}+[a_i\not =a_{i-1}],f_{i-1,1}+[a_i\not=a_{i-2}])\\ f_{i,1}=1+[a_i\not=a_{i-1}]+\min(f_{i-2,0}+[a_i\not=a_{i-2}],f_{i-2,1}+[a_i\not=a_{i-3}]) \end{cases}
所以楼上 dp 方程似乎错了?

code

CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int mod=998244353;
int n,m,a[N],ans;
int f[N][2];
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	f[1][0]=1,f[1][1]=mod;
	for(int i=2;i<=n;i++){
		f[i][0]=min(f[i-1][0]+(a[i]!=a[i-1]),f[i-1][1]+(a[i]!=a[i-2]));
		f[i][1]=1+(a[i]!=a[i-1])+f[i-2][0]+(a[i]!=a[i-2]);
		if(i>2) f[i][1]=min(f[i][1],1+(a[i]!=a[i-1])+f[i-2][1]+(a[i]!=a[i-3]));
	}
	cout<<min(f[n][0],f[n][1])<<"\n";
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int _;
	cin>>_;
	while(_--) solve();
	return 0;
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...