Codeforces Round #592 (Div. 2) F. Chips

https://codeforces.com/contest/1244/problem/F

题意:

给你一个由n个点围成的环,初始状态下环上每一个点都有黑或者白两种状态,此时要进行k次变换

每次变换,对于某个点,其颜色为这个点以及其左右两边的两个点上较多的颜色,用W表示白色,B表示黑色,则 BWB 这三个点中间的W下一次应该变为黑色

问进行k次变换之后每个点的颜色是什么。

 

 

1.假如有两个以上的点是相同的颜色,那么无论如何变换这两个点都不会变色,所以一开始可以将这样的找出来作个标记

2.对于某段由相同颜色组成的段,每一次变换都会将段两端的点变为段的颜色

比如

BWBWWWBWBW 

第一次: WBWWWWWBWB

第二次:BWWWWWWWBW

第三次:WWWWWWWWWB

第四次:WWWWWWWWWW

3.什么时候趋于稳定(如何变化都不会改变点的颜色),只有当换上所有点都属于任何一个段的时候

比如 BWWBBWWB,每个点都属于一个段,此时稳定

 

那么对于那些不属于段的点,我们计算出其距离最近段的距离,和k比较,就可以直到这个点最后是什么颜色了

怎么计算距离呢,顺着找一次,逆着找一次

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 7;
int dis[maxn], num[maxn], flag[maxn];
//dis:最近段距离 , num:颜色  flag:点是否属于一个段
int n, k, hav;
//hav:环中是否有段
char inp[maxn];
int main() {
	memset(dis, INF, sizeof(dis));
	cin >> n >> k;
	scanf("%s", inp + 1);
	for (int i = 1; i <= n; i++) {
		if (inp[i] == 'B') num[i] = 1;
	}
	//构造flag数组
	for (int i = 2; i <= n; i++) {
		if (num[i] == num[i - 1])
			flag[i] = flag[i - 1] = 1, hav = 1;
	}
	if (num[1] == num[n]) flag[1] = flag[n] = 1, hav = 1;

	int near = 0;//near: 表示最近的段的下标
	if (hav == 0)//假如没段,直接去结尾
		goto to;
	//顺着
	for(int i=n;i;i--)//最开始的点最近的段可能在1的左边
		if (flag[i] == 1) {
			near = -i; //特别标记为负数,便于识别
			break;
		}
	for (int i = 1; i <= n; i++) {
		if (!flag[i]) {
			if (near < 0) {
				dis[i] = n + near + i;
			}
			else dis[i] = i - near;
		}
		else near = i;
	}
	//逆着
	for(int i=1;i<=n;i++)
		if (flag[i] == 1) {
			near = -i;
			break;
		}
	for (int i = n; i; i--) {
		if (!flag[i]) {
			if (near < 0) {
				dis[i] = min(-near + n - i, dis[i]);
			}
			else dis[i] = min(near - i, dis[i]);
		}
		else near = i;
	}
to:	int times;
	for (int i = 1; i <= n; i++) {
		if (flag[i] == 1) putchar(inp[i]);
		else {
			times = min(k, dis[i]);
			times %= 2;
			if (times == 0) putchar(inp[i]);
			else putchar((inp[i] == 'W' ? 'B' : 'W'));
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值