[atAGC052E]3 Letters

当$n=1$时,答案显然为0或1,以下不妨假设$n\ge 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 1\le 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 1\le i\le n,A_{i}\equiv S_{i}(mod\ 3)$

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

首先,当$S$对应$A$,那么有$\forall 2\le i\le 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}\not\equiv B_{1}(mod\ 2)$即不存在$p_{i}$,否则最小的$k$为$\frac{\sum_{i=1}^{n}|A_{i}-B_{i}|}{2}$

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

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

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

事实上,只需要证明$\exists i,A_{i}\ne 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}+1\ge 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,显然不影响其任何性质,因此不妨假设$0\le 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}|$,求当$3\mid x$时的最小值

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

最终,总时间复杂度为$o(n)$或$o(n\log 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

 

posted @ 2021-05-12 15:35  PYWBKTDA  阅读(104)  评论(0)    收藏  举报