Luogu P11361 NOIP2024 編輯字串 題解 [ 黃 ] [ 貪心 ]

KS_Fszha發表於2024-12-07

編輯字串:這題能評藍已經說明了洛谷的唐氏。

結論

找到兩個字串種連續的且可以移動的所有極大子區間,然後線性掃一遍,看這一位所處的子區間中有多少個 \(0\)\(1\),兩個都有 \(0\) 就先消 \(0\),否則如果兩個都有 \(1\) 就把 \(1\) 消掉,就做完了。

時間 \(O(Tn)\)

證明

洛谷上有一種很妙的證明,借鑑一下。

這題的答案顯然是:

\[n-\sum_{i=1}^{n}(a_i-b_i)^2=n-(\sum_{i=1}^{n}(a_i^2+b_i^2-2a_ib_i)) \]

\[=n-(\sum_{i=1}^{n}a_i^2+\sum_{i=1}^{n}b_i^2-\sum_{i=1}^{n}2a_ib_i) \]

\[=n-\sum_{i=1}^{n}a_i^2-\sum_{i=1}^{n}b_i^2+\sum_{i=1}^{n}2a_ib_i \]

顯然 \(n\)\(\sum_{i=1}^{n}a_i^2\)\(\sum_{i=1}^{n}b_i^2\) 已經是定值,那麼我們要最大化 \(\sum_{i=1}^{n}2a_ib_i\),就要把 \(a_i,b_i\) 先全部放 \(1\)

由於這題 \(0\)\(1\) 具有對稱性,所以先全部放 \(0\) 也是對的。

程式碼

程式碼也不難寫,考場上 10min 打完的,思路也就想了 10min,還包括手模樣例的時間。

這題做出來不能說明強,但是真正強的絕對會這題,那些自稱強的還做不出來的純屬基礎不牢,菜就多練。天天升升升的升你媽呢。

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,cnta,cntb,bla[100005],blb[100005],tota[100005][2],totb[100005][2],ans;
bitset<100005>a,b,ta,tb;
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        char x;
        cin>>x;
        a[i]=(x-'0');
    }
    for(int i=1;i<=n;i++)
    {
        char x;
        cin>>x;
        b[i]=(x-'0');
    }
    cnta=0;
    for(int i=1;i<=n;i++)
    {
        char x;
        cin>>x;
        ta[i]=(x-'0');
        if(ta[i]!=ta[i-1]||ta[i]==0)cnta++;
        bla[i]=cnta;
    }
    cntb=0;
    for(int i=1;i<=n;i++)
    {
        char x;
        cin>>x;
        tb[i]=(x-'0');
        if(tb[i]!=tb[i-1]||tb[i]==0)cntb++;
        blb[i]=cntb;
    }
    memset(tota,0,sizeof(tota));
    memset(totb,0,sizeof(totb));
    for(int i=1;i<=n;i++)
    {
        tota[bla[i]][a[i]]++;
        totb[blb[i]][b[i]]++;
    }
    ans=0;
    for(int i=1;i<=n;i++)
    {
        if(tota[bla[i]][0]>0&&totb[blb[i]][0]>0)
        {
            ans++;
            tota[bla[i]][0]--;
            totb[blb[i]][0]--;
        }
        else if(tota[bla[i]][1]>0&&totb[blb[i]][1]>0)
        {
            ans++;
            tota[bla[i]][1]--;
            totb[blb[i]][1]--;
        }
    }
    cout<<ans<<'\n';
}
int main()
{
    freopen("edit.in","r",stdin);
    freopen("edit.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--)solve();
    return 0;
}

相關文章