Codeforces 1244F. Chips

传送门

显然可以注意到连续的两个相同颜色的位置颜色是不会改变的,并且它还会把自己的颜色每秒往外扩展一个位置

同时对于 $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;
}
原文地址:https://www.cnblogs.com/LLTYYC/p/11675247.html