• [atAGC052E]3 Letters


    当$n=1$时,答案显然为0或1,以下不妨假设$nge 2$

    为了方便,以下将${A,B,C}$分别看作${0,1,2}$,下标都为$[1,n]$

    假设我们要修改$S_{i}$,必然要有$i$为端点(1和$n$)或$S_{i-1}=S_{i+1}$,同时修改的结果也是唯一的

    因此,不妨用一个二元组$(S,i)$,来描述修改$S_{i}$后的字符串(若不可以修改不妨记作$S$)

    从中,问题也可以看作构造序列$p_{i}$,使得$(((S,p_{1}),p_{2}),...,p_{k})=T$并最小化$k$

    称一个整数序列$A$连续,当且仅当$forall 1le i<n,|A_{i}-A_{i+1}|=1$

    对于一个整数序列$A$,可以选择$A_{i}$加上或减去2,并使得操作后的序列仍然连续

    类似地,修改$A_{i}$的条件也是$i$为端点或$A_{i-1}=A_{i+1}$,同时修改的结果也唯一,同样用二元组$(A,i)$来描述修改$A_{i}$后的整数序列(若不可以记作$A$)

    对于合法字符串$S$,称其对应整数序列$A$,当且仅当$A$连续且$forall 1le ile n,A_{i}equiv S_{i}(mod 3)$

    结论:若$S$对应$A$,则$(S,i)$对应$(A,i)$

    首先,当$S$对应$A$,那么有$forall 2le ile n$,$S_{i-1}=S_{i+1}$与$A_{i-1}=A_{i+1}$是等价的:

    1.若$A_{i-1}=A_{i+1}$,即有$S_{i-1}equiv S_{i+1}(mod 3)$,又因为$S_{i}in {0,1,2}$,即有$S_{i-1}=S_{i+1}$

    2.若$S_{i-1}=S_{i+1}$,即有$A_{i-1}equiv A_{i+1}(mod 3)$,若两者不等必有$|A_{i-1}-A_{i+1}|ge 3$,同时根据其相邻的性质,有$|A_{i-1}-A_{i+1}|le |A_{i-1}-A_{i}|+|A_{i}-A_{i+1}|=2$,即矛盾

    因此若不能对$i$操作,两者都不能,那么必然有$(S,i)=S$且$(A,i)=A$,显然对应

    当$i$可以操作,显然${(A,i)_{i},A_{i},A_{i-1}}$构成模3的完系,也即$(A,i)_{i}+A_{i}+A_{i-1}equiv 0(mod 3)$

    根据$S$对应$A$,有$(A,i)_{i}equiv -(S_{i}+S_{i-1})(mod 3)$,类似地${(S,i)_{i},S_{i},S_{i-1}}$也构成模3的完系(实际上是恰为${0,1,2}$),因此有$(S,i)_{i}equiv -(S_{i}+S_{i-1})equiv (A,i)_{i}(mod 3)$,即成立

    推论:$(((S,p_{1}),p_{2}),...,p_{k})=T$等价于存在$A$和$B$满足$S$对应$A$、$T$对应$B$且$(((A,p_{1}),p_{2}),...,p_{k})=B$

    必要性:当$(((S,p_{1}),p_{2}),...,p_{k})=T$,根据前面的结论任取$S$对应$A$都有$T$对应$(((A,p_{1}),p_{2}),...,p_{k})$,令后者为$B$即满足条件

    充分性:当后者满足时,取$A$和$B$满足此条件,则有$(((S,p_{1}),p_{2}),...,p_{k})$对应$B$,再根据$T$对应$B$不难得到$T_{i}equiv (((S,p_{1}),p_{2}),...,p_{k})_{i}(mod 3)$,由于两者范围都为${0,1,2}$,即$T=(((S,p_{1}),p_{2}),...,p_{k})$

    综上,我们不妨将题目条件转换为后者

    假设暴力枚举$A$和$B$,来考虑构造序列$p_{i}$,使得$(((A,p_{1}),p_{2}),...,p_{k})=B$并最小化$k$,那么对每一对$(A,B)$都求出此答案后取$min$即可

    结论:若$A_{1} otequiv B_{1}(mod 2)$即不存在$p_{i}$,否则最小的$k$为$frac{sum_{i=1}^{n}|A_{i}-B_{i}|}{2}$

    首先,每一次的操作是$pm2$,因此$A_{1} otequiv B_{1}(mod 2)$时显然无解

    根据连续性,$A_{i}$确定$A_{i+1}$的奇偶性,因此若$A_{1}equiv B_{1}(mod 2)$,即有$forall 1le ile n,A_{i}equiv B_{i}(mod 2)$

    关于最小的$k$,显然是下限,下面来证明其可以被取到

    事实上,只需要证明$exists i,A_{i} e B_{i}$时,存在操作$(A,i)$使得$frac{sum_{j=1}^{n}|(A,i)_{j}-B_{j}|}{2}$减小1,归纳即可证明此结论

    不妨假设$exists i,A_{i}>B_{i}$($exists i,A_{i}<B_{i}$是类似的),取$A_{i}>B_{i}$中$A_{i}$最大的位置(多个任取)为$j$,考虑执行操作$(A,j)$,下面来说明其正确性——

    当$j>1$时,必然有$A_{j-1}le A_{j}$,否则即$A_{j-1}ge A_{j}+1>B_{j}+1ge B_{j-1}$,显然$A_{j-1}$更大,即矛盾

    同时,根据$|A_{j-1}-A_{j}|=1$的性质,可以得到$A_{j-1}=A_{j}-1$

    类似地,也可以得到当$j<n$,有$A_{j+1}=A_{j}-1$

    因此,这一次操作必然是可以执行,且必然是令$A_{j}$减小2,由于$A_{j}equiv B_{j}(mod 2)$,减小即令$|(A,i)_{j}-B_{j}|$减小2,也即$frac{sum_{j=1}^{n}|(A,i)_{j}-B_{j}|}{2}$减小1,因此成立

    综上,问题又可以变成:取$A,B$满足$S$对应$A$、$T$对应$B$且$A_{1}equiv B_{1}(mod 2)$,并最小化$frac{sum_{i=1}^{n}|A_{i}-B_{i}|}{2}$

    将所有$A_{i}$和$B_{i}$不断减去或加上3,显然不影响其任何性质,因此不妨假设$0le A_{1}<3$,即有$A_{1}=S_{1}$,进而即可确定序列$A$

    通过$A_{1}$和$T_{1}$,即可确定$B_{1}$模6的余数,将这个余数作为$B_{1}$并将得到的序列记作$C$,那么所有序列$B$即在$C$的基础上将所有$b_{i}$加上或减去6

    很明显,$B$可以用一个整数$x$描述,即$B_{i}=6x+C_{i}$,因此即最小化$frac{sum_{i=1}^{n}|6x-(A_{i}-C_{i})|}{2}$

    令$D_{i}=frac{A_{i}-C_{i}}{2}$,即最小化$sum_{i=1}^{n}|3x-D_{i}|$,可以将其看作关于$3x$的函数,即令$f(x)=sum_{i=1}^{n}|3x-D_{i}|$,求当$3mid x$时的最小值

    令中位数$x_{0}=D_{lfloorfrac{n+1}{2} floor}$(排序后),显然在$x_{0}$左右两侧单调不增和单调不减,因此最小值显然在$x_{0}$两侧第一个$3mid x$的位置取到,计算即可

    最终,总时间复杂度为$o(n)$或$o(nlog n)$(排序),可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 500005
     4 #define ll long long
     5 int n,ans,a[N],b[N],c[N];
     6 char s[N],t[N];
     7 ll calc(int x){
     8     ll ans=0;
     9     for(int i=0;i<n;i++)ans+=abs(3*x-c[i]);
    10     return ans;
    11 }
    12 int main(){
    13     scanf("%d%s%s",&n,s,t);
    14     if (n==1){
    15         printf("%d",(s[0]!=t[0]));
    16         return 0;
    17     }
    18     a[0]=s[0]-'A';
    19     for(int i=1;i<n;i++){
    20         if ((a[i-1]%3+4)%3==s[i]-'A')a[i]=a[i-1]+1;
    21         else a[i]=a[i-1]-1;
    22     }
    23     b[0]=t[0]-'A';
    24     if (b[0]%2!=a[0]%2)b[0]+=3;
    25     for(int i=1;i<n;i++){
    26         if ((b[i-1]%3+4)%3==t[i]-'A')b[i]=b[i-1]+1;
    27         else b[i]=b[i-1]-1;
    28     }
    29     for(int i=0;i<n;i++)c[i]=(a[i]-b[i])/2;
    30     sort(c,c+n);
    31     int x=c[n/2];
    32     if (x>=0)printf("%lld",min(calc(x/3),calc(x/3+1)));
    33     else printf("%lld",min(calc(x/3),calc(x/3-1)));
    34 } 
    View Code
  • 相关阅读:
    在线图片压缩
    wiki-editor语法
    Android 4.0.4模拟器安装完全教程(图文)
    Javascript中的void
    守护进程
    jQuery编程的最佳实践
    JavaScript内存优化
    vim编程技巧
    MySQL表的四种分区类型
    SQL中的where条件,在数据库中提取与应用浅析
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14760056.html
Copyright © 2020-2023  润新知