显然可以注意到连续的两个相同颜色的位置颜色是不会改变的,并且它还会把自己的颜色每秒往外扩展一个位置
同时对于 $BWBWBW...$ 这样的序列,它每个位置的颜色每一秒变化一次
然后可以发现,对于一个位置 $x$,在 $x$ 左边和右边 连续两个相同颜色 扩展到 $x$ 之前, $x$ 的颜色一定是每秒变化一次
考虑每个位置 $x$ 第 $k$ 秒时的颜色,如果 $x$ 初始往 左或者往右的连续两个相同颜色 扩展到 $x$ 的时间都大于 $k$ ,那么我们可以通过 $k$ 的奇偶性和 $x$ 的初始颜色 求出最终的颜色
如果 $x$ 初始往左或者往右的 连续两个相同颜色 扩展到 $x$ 的时间小于 $k$ ,那么需要时间比较小的那边就会先把 $x$ 同化
所以我们可以通过预处理出每个位置往左和往右第一个 连续两个相同颜色 来判断每个位置最终的颜色
实现看代码吧
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e5+7; int n,m,L[N],R[N]; char s[N],ans[N]; vector <int> pos; bool vis[N]; int main() { n=read(),m=read(); scanf("%s",s+1); for(int i=1;i<=n;i++) { int l=(i+n-2)%n+1,r=i%n+1; if(s[l]==s[i]||s[r]==s[i]) pos.push_back(i),vis[i]=1; } int len=pos.size(); if(!len) { for(int i=1;i<=n;i++) ans[i]= (s[i]=='W' ^ (m&1)) ? 'W' : 'B'; for(int i=1;i<=n;i++) printf("%c",ans[i]); puts(""); return 0; } int las=pos[len-1]; for(int i=1;i<=n;i++) if(vis[i]) las=i; else L[i]=las; las=pos[1]; for(int i=n;i>=1;i--) if(vis[i]) las=i; else R[i]=las; for(int i=1;i<=n;i++) { if(vis[i]) { ans[i]=s[i]; continue; } int Ld=(i-L[i]+n)%n,Rd=(R[i]-i+n)%n; if(min(Ld,Rd)>m) ans[i]= (s[i]=='W' ^ (m&1)) ? 'W' : 'B'; else ans[i]= (Ld<Rd) ? s[L[i]] : s[R[i]]; } for(int i=1;i<=n;i++) printf("%c",ans[i]); puts(""); return 0; }