• Japanese Student Championship 2021


    Japanese Student Championship 2021

    E - Level K Palindrome

    思路简单(?,代码调试半年。

    做的路上出去口胡了2道莫队再回来做题,回来就想出了大框架,然后是各种细节调调调,然后调了3h+,中途换写法。

    开始分析:(严肃脸

    首先很 naive 的一个结论:

    这个 level (k) 的串所对应的 level (0) 的串的长度是确认的。

    啊?你说样例 (1) 不满足?那确实,因为长度为 (1) 的串都为 level (1)

    这点需要特判处理。

    我们可以处理出每一个位置对应相等的位置。(分治,然后回文对应相等,可以看代码理解)

    这个信息用并查集维护。

    然后按位贪心就可以了。

    但是注意,按位贪心后得出的串是一个 level (0) 的串,所以这个串必须不回文。

    那么在这个串已经是回文的情况下:

    我们想要强制这个串不回文的同时保证答案最小,就是将一个位置出现次数最大的字符换为这个位置出现次数次大的字符

    这道题 差不多 就做完了

    时间复杂度:(O(nlogn)) (n为字符串长度)

    当然也只能是差不多做完了,还有好几个害人的细节:

    毒瘤的细节:

    1.判断无解时需要 (2^k) 这个东西,但是(kleq10^5) 防止爆 (int) 需要在无解中再加一个条件

    2.如果最后得出的串是一个奇回文,那么不能替换中间的那个字符,只能替换两侧的字符

    3.无解的条件中,最小的边界为 $2^{k-1} $ 所以应该是 (<) 而不是 (leq)

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;return;
    }
    template <typename T>
    inline void print(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) print(x/10);
        putchar(x%10^48);return;
    }
    const int N=5e5+3,K=5e5+3,INF=0x3f3f3f3f;
    int k;
    int fa[N],tong[N][30],maxn[N],emaxn[N],bel[N];
    char s[N];
    inline int Get(int x){return x==fa[x] ? x : fa[x]=Get(fa[x]);}
    inline void Merge(int x,int y){fa[Get(x)]=Get(y);return;}
    
    inline void Split(int l,int r,int dep){
        if(!dep)    return;
        int len=(r-l+1);
        if(len&1)   Split(l,l+len/2-1,dep-1),Split(l+len/2+1,r,dep-1);
        else Split(l,l+len/2-1,dep-1),Split(l+len/2,r,dep-1);
        int mid=(l+r)>>1;
        for(register int i=0;r-i>=mid;++i){Merge(r-i,l+i);}
        return;
    }
    inline bool Judge(int len){
        for(register int i=1;i<=len;++i)    if(bel[i]!=bel[len-i+1])    return true;
        return false;
    }
    vector<int> res;
    int main(){
        read(k);
        scanf("%s",s+1);
        int len=strlen(s+1);
        if(k>=20||len/(1<<k)==1||len<(1<<(k-1))){puts("impossible");return 0;}
        for(register int i=1;i<=len;++i)    fa[i]=i;
        int anslen=len,t=k;
        while(t--){
            if(anslen&1) anslen=(anslen-1)>>1;
            else anslen>>=1;
        }
        Split(1,len,k);
        for(register int i=1;i<=len;++i){
            tong[Get(i)][s[i]-'a']++;
            if(Get(i)==i)   res.push_back(i);
        }
        int siz=res.size(),ans=0;
        for(register int i=0;i<siz;++i){
            int x=res[i];
            for(register int j=0;j<26;++j){
                if(maxn[x]<tong[x][j])    bel[x]=j,emaxn[x]=maxn[x],maxn[x]=tong[x][j];
                else emaxn[x]=max(emaxn[x],tong[x][j]);
            }
        }
        for(register int i=0;i<siz;++i)    ans+=maxn[res[i]];
        if(!anslen){print(len-ans);return 0;}
        if(!Judge(anslen)){
            int minn=INF;bool f=false;
            if(anslen&1)    f=true;
            for(register int i=1;i<=anslen;++i){
                if(f&&anslen/2+1==i)    continue;
                minn=min(minn,maxn[i]-emaxn[i]);
            }
            ans-=minn;
        }
        print(len-ans);
        return 0;
    }
    
    
  • 相关阅读:
    软工实践第三次作业(结对第一次作业)
    软工实践第四次作业(团队展示)
    软工实践第二次作业(词频统计)
    软工实践第七次作业(软件产品案例分析 )
    安装cordova和ionic遇到cordova v和ionic v出错的问题,出现SyntaxError
    软工实践第八次作业(软件工程实践总结)
    软工实践第六次作业(团队项目作业汇总)
    软工实践第五次作业(结对第二次作业)
    chain of responsibilit职责链模式
    术语
  • 原文地址:https://www.cnblogs.com/NuoCarter/p/14730137.html
Copyright © 2020-2023  润新知