1 条题解
-
0
自动搬运
来自洛谷,原作者为

Bingxiu2
蓝名搬运于
2025-08-24 23:06:42,当前版本为作者最后更新于2024-12-03 18:33:08,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
没去 NOIP,今天在学校里某同学告诉我今年 T1 非常难打,他打了 多行
所以回来打了一下, 开题, AC
发篇题解
炫耀一下考虑贪心,从左到右每个字符能匹配就匹配。
显然是对的,因为匹配这一对字符至多会导致后面的一对字符不匹配。
但是很多题解到这一步开始就过于复杂了,各种分段模拟的方法码量都很大。
这里提供一种简单的方法。
考虑预处理两个数组,记录每个字符所在可以交换的连续段(后面简称段)的编号,只要从左往右判断每个字符和上一个字符是否可以交换,可以的就和上一个字符在同一段,否则作为一个新段。
再预处理每一段还有多少个没有使用的 ,同样从左到右把每个字符所在的段对应变量加 即可。
然后从左到右,每次判断对应的两个字符 所在段是否有相同的未使用的字符,有的话按照贪心直接取并将使用的字符在对应段的变量 ,否则将对应段还有的字符的变量分别 。
最后一个细节问题:如果一个字符不能被交换该怎么办?
大部分题解都选择分类讨论,但是这里不用,因为预处理的时候考虑的是和上一个字符是否可以交换,所以不能交换的字符在单独的一段中,满足要求。
现在就有一个 分钟以内能写完调完的解法了。
#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; }让我看看还有谁抱怨写不完
- 1
信息
- ID
- 11035
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者