「杂题乱刷2」CF2069D

更不好的阅读体验

题目链接

CF2069D(*1900) Palindrome Shuffle(luogu)

CF2069D(*1900) Palindrome Shuffle(codeforces)

解题思路

本文 V 代表 26,即字符集大小。

这题是史,大家一起吃。

首先根据题中定义这题显然长度为 i(i<n) 合法,则长度为 i+1 合法,因为你可以任意交换,不影响。

因此此题可以二分答案。

那么容易得出 check 一个长度 len 是否合法只需要判断是否有至少一个长度为 len 的区间合法即可,那么我们考虑如何进行 check 一个任意交换区间 [l,r] 是否合法,首先通过提前预处理判断掉不能任意交换且字母本应该相同的位置是否合法,处理完这个之后此时我们可以考虑分讨以下几种情况:

  • rn2,此时整个可交换的区间都在左边,只需要前缀和即可 O(V) 判断一个区间是否合法。

  • l>n2,此时整个可交换的区间都在右边,只需要前缀和即可 O(V) 判断一个区间是否合法。

  • ln2<r,则此时可交换区间包含左右两边,此时我们继续分讨:

    • n2l<rn2,此时我们只需要判断左边是否能暴力匹配右边的字母即可。

    • n2lrn2,此时我们只需要判断右边是否能暴力匹配左边的字母即可。

那么 check 就做完了,那么整题也就做完了,最后是一个二分板子,不赘述。

时间复杂度 O(nVlogn),可以通过本题。

参考代码

string s;
ll n;
ll pre[200010];
ll sum[200010][30];
ll now[30];
bool PRE(ll len){
    return pre[len]==len;
}
bool ck(ll l,ll r)
{
    if(l==1 && r==n)
        return 1;
    ll l1,l2,r1,r2;
    l1=1,r1=l-1;
    l2=r+1,r2=n;
    ll len=min(r1,n-l2+1);
    if(!PRE(len))
        return 0;
    if(l+r==n+1)
        return 1;
    forl(i,0,25)
        now[i]=sum[r][i]-sum[l-1][i];
    if(l<=n/2 && r<=n/2)
    {
        if(r!=n/2 && pre[n/2]-pre[r]!=n/2-r)
            return 0;
        forl(i,0,25)
            if(now[i]!=sum[n+1-l][i]-sum[n+1-r-1][i])
                return 0;
        return 1;
    }
    else if(l>n/2 && r>n/2)
    {
        if(l!=n/2+1 && pre[n/2]-pre[n+1-l]!=n/2-(n+1-l))
            return 0;
        forl(i,0,25)
            if(now[i]!=sum[n+1-l][i]-sum[n+1-r-1][i])
                return 0;
        return 1;
    }
    else
    {
        if(n/2-l<r-n/2)
        {
       //   bug2;
            forl(i,0,25)
            {
                now[i]-=sum[n+1-(n+1-l)-1][i]-sum[n+1-r-1][i];
                if(now[i]<0)
                    return 0;
            }
            /*
            r,r-1,n-l
            */
            ///////
            // while(l+r>n+1)
            // {
            //     //r--;
            //  //   cout<<s[n+1-r]<<endl;
            //     if(!now[s[n+1-r]-'a']--)
            //         return 0;
            //     r--;
            // }
        //    bug3;
            forl(i,0,25)
                if(now[i]&1)
                    return 0;
            return 1;
        }
        else
        {
            forl(i,0,25)
            {
                now[i]-=sum[n+1-l][i]-sum[n+1-(n+1-r)][i];
                if(now[i]<0)
                    return 0;
            }
       //  bug1;
            // while(l+r<n+1)
            // {
            //     //l++;
            //     if(!now[s[n+1-l]-'a']--)
            //         return 0;
            //     l++;
            // }
         // bug4;
            forl(i,0,25)
                if(now[i]&1)
                    return 0;
            return 1;
        }
    }
}
bool check(ll Mid)
{
    forl(i,1,n-Mid+1)
        if(ck(i,i+Mid-1))   
            return 1;
    return 0;
}
ll L,R;
/*
ababa babababab
ababa babb ababa
*/
void _clear(){}
void solve()
{
    _clear();
    cin>>s;
    n=s.size();
    s=' '+s;
    forl(i,1,n)
    {
        forl(j,0,25)
            sum[i][j]=sum[i-1][j];
        sum[i][s[i]-'a']++;
    }
    forl(i,1,n)
        pre[i]=0;
    forl(i,1,n/2)
        pre[i]=(s[i]==s[n-i+1]);
    forl(i,1,n/2)
        pre[i]+=pre[i-1];
    if(pre[n/2]==n/2)
    {
        cout<<0<<endl;
        return ;
    }
   // cout<<ck(5,10)<<endl;
   // return ;
    L=1,R=n;
    while(L<R)
    {
        ll Mid=(L+R)/2;
        if(check(Mid))
            R=Mid;
        else
            L=Mid+1;
    }
    cout<<L<<endl;
}
posted @   wangmarui  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
历史上的今天:
2024-03-03 「杂题乱刷」洛谷 P4801
2024-03-03 「杂题乱刷」CF1934D2
点击右上角即可分享
微信分享提示