CodeForces - 908F New Year and Rainbow Roads
阿新 • • 發佈:2020-08-24
\(\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; }