1 条题解

  • 0
    @ 2025-8-24 23:06:42

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Bingxiu2
    蓝名

    搬运于2025-08-24 23:06:42,当前版本为作者最后更新于2024-12-03 18:33:08,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    没去 NOIP,今天在学校里某同学告诉我今年 T1 非常难打,他打了 100100 多行

    所以回来打了一下,2024/12/3 18:092024/12/3\ 18:09 开题,2024/12/3 18:272024/12/3\ 18:27 AC

    发篇题解炫耀一下

    考虑贪心,从左到右每个字符能匹配就匹配。

    显然是对的,因为匹配这一对字符至多会导致后面的一对字符不匹配。

    但是很多题解到这一步开始就过于复杂了,各种分段模拟的方法码量都很大。

    这里提供一种简单的方法。

    考虑预处理两个数组,记录每个字符所在可以交换的连续段(后面简称段)的编号,只要从左往右判断每个字符和上一个字符是否可以交换,可以的就和上一个字符在同一段,否则作为一个新段。

    再预处理每一段还有多少个没有使用的 0/10/1,同样从左到右把每个字符所在的段对应变量加 11 即可。

    然后从左到右,每次判断对应的两个字符 s1,i,s2,is_{1,i},s_{2,i} 所在段是否有相同的未使用的字符,有的话按照贪心直接取并将使用的字符在对应段的变量 1-1,否则将对应段还有的字符的变量分别 1-1

    最后一个细节问题:如果一个字符不能被交换该怎么办?

    大部分题解都选择分类讨论,但是这里不用,因为预处理的时候考虑的是和上一个字符是否可以交换,所以不能交换的字符在单独的一段中,满足要求。

    现在就有一个 1010 分钟以内能写完调完的解法了。

    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;
    }
    

    让我看看还有谁抱怨写不完

    • 1

    信息

    ID
    11035
    时间
    1000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者