P11361 [NOIP2024] 编辑字符串 一种非常简单的解法
没去 NOIP,今天在学校里某同学告诉我今年 T1 非常难打,他打了
所以回来打了一下,
发篇题解炫耀一下
考虑贪心,从左到右每个字符能匹配就匹配。
显然是对的,因为匹配这一对字符至多会导致后面的一对字符不匹配。
但是很多题解到这一步开始就过于复杂了,各种分段模拟的方法码量都很大。
这里提供一种简单的方法。
考虑预处理两个数组,记录每个字符所在可以交换的连续段(后面简称段)的编号,只要从左往右判断每个字符和上一个字符是否可以交换,可以的就和上一个字符在同一段,否则作为一个新段。
再预处理每一段还有多少个没有使用的
然后从左到右,每次判断对应的两个字符
最后一个细节问题:如果一个字符不能被交换该怎么办?
大部分题解都选择分类讨论,但是这里不用,因为预处理的时候考虑的是和上一个字符是否可以交换,所以不能交换的字符在单独的一段中,满足要求。
现在就有一个
AC Code
#include<bits/stdc++.h>
using namespace std;
int t,n,ans,p[100009],q[100009],e[100009],f[100009],g[100009],h[100009];
string a,b,c,d;
int main(){
cin>>t;
while(t--){
cin>>n>>a>>b>>c>>d,p[0]=q[0]=0,(a[0]&1)?++f[0]:++e[0],(b[0]&1)?++h[0]:++g[0],ans=0;
for(int i=1;i<n;++i) p[i]=((c[i]&1)&&(c[i-1]&1)?p[i-1]:i),(a[i]&1)?++f[p[i]]:++e[p[i]];
for(int i=1;i<n;++i) q[i]=((d[i]&1)&&(d[i-1]&1)?q[i-1]:i),(b[i]&1)?++h[q[i]]:++g[q[i]];
for(int i=0;i<n;++i){
if(e[p[i]]&&g[q[i]]) ++ans,--e[p[i]],--g[q[i]];
else if(f[p[i]]&&h[q[i]]) ++ans,--f[p[i]],--h[q[i]];
else if(e[p[i]]) --e[p[i]],--h[q[i]];
else --f[p[i]],--g[q[i]];
}
cout<<ans<<"\n";
}
return 0;
}
让我看看还有谁抱怨写不完