码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces - 908F New Year and Rainbow Roads

时间:2020-08-28 14:40:45      阅读:56      评论:0      收藏:0      [点我收藏+]

标签:选择删除   text   har   for   amp   include   while   -o   ==   

\(\text{Solution}\)

首先,红点只能与红点和绿点相连,蓝点只能与蓝点和绿点相连。

假设两个相邻绿点(这里的相邻是编号上的相邻)中间一堆红点和蓝点,我们一定把红点蓝点分别顺次连接就像这样:

技术图片

显然红蓝点这样连成一条链再连上绿点要比一个个连上绿点要优。

我们继续考虑上图,发现并不需要连这么多条边。我们可以选择删除一条 \((G,G)\) 或一条端点有红点的和一条端点有蓝点的,取个 \(\min\) 就是这一段的答案,最后累加起来就醒了。

\(\text{Code}\)

#include<cstdio>
#include<iostream>
using namespace std;

int n, ans, x[(int) 3e5 + 2], maxR, maxB, lastR, lastB, lastG;

int read() {
	int x = 0, f = 1; char s;
	while((s = getchar()) > ‘9‘ || s < ‘0‘) if(s == ‘-‘) f = -1;
	while(s >= ‘0‘ && s <= ‘9‘) {
		x = (x << 1) + (x << 3) + (s ^ 48);
		s = getchar();
	}
	return x * f;
}

int main() {
	char op;
	n = read();
	for(int i = 1; i <= n; ++ i) {
		x[i] = read(); op = getchar();
		if(op == ‘G‘ || op == ‘R‘) {
			if(lastR) ans += x[i] - x[lastR], maxR = max(maxR, x[i] - x[lastR]);
			lastR = i;
		}
		if(op == ‘G‘ || op == ‘B‘) {
			if(lastB) ans += x[i] - x[lastB], maxB = max(maxB, x[i] - x[lastB]);
			lastB = i;
		}
		if(op == ‘G‘) {
			if(lastG) ans += min(0, x[i] - x[lastG] - maxR - maxB);//之前算的是不连绿点的贡献
			lastG = i;
			maxR = maxB = 0;
		}
	}
	printf("%d\n", ans);
	return 0;
}

CodeForces - 908F New Year and Rainbow Roads

标签:选择删除   text   har   for   amp   include   while   -o   ==   

原文地址:https://www.cnblogs.com/AWhiteWall/p/13552889.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!