CodeForces

( ext{Solution})

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

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

在这里插入图片描述

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

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

( ext{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
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/13552889.html