T735849 白光 (light) 赛后题解

题目传送门

思路

因为每次只能熄灭最左侧或者最右侧,所以最后亮着的灯一定是连续的。
显然,如果要熄灭一段的灯,那么得比全部换灯的颜色的代价少。
显然,那些不能让最后亮着的灯的个数为 \(3\) 的倍数的边上的灯必须熄灭。(即至少共熄灭 \(n\ \%\ 3\) 盏两边的灯)

做法

枚举一定要熄灭掉前面 \(0\)\(2\) 盏灯,进行贪心。
\(3\) 盏灯为一组,算出从可以留的第一盏灯与最后一盏灯开始全部换色与关掉的代价,进行比较。
找到两个位置 lposrpos,为满足从留的第一盏灯与最后一盏灯开始,关灯比换色的代价差最大的位置。
如果满足 lpos>=rpos,则说明全部关掉最好。

时间复杂度:\(O(n)\),可以通过 \(n\le2\times10^5\)

代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[300005];
int A, B, C;
int calc(int pos)
{
	int ret = 0;
	if(a[pos] != 1) ret += C;
	if(a[pos + 1] != 2) ret += C;
	if(a[pos + 2] != 3) ret += C;
	return ret;
}
int l[300005], r[300005], c[300005];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	freopen("light.in", "r", stdin);
	freopen("light.out", "w", stdout);
	int n;
	cin >> n;
	string s;
	cin >> s;
	s = ' ' + s;
	for(int i = 1; i <= n; i ++)
	{
		if(s[i] == 'R') a[i] = 1;
		else if(s[i] == 'G') a[i] = 2;
		else a[i] = 3;
	}
	cin >> A >> B >> C;
	int ans = 2e18;
	for(int st = 1; st <= 3; st ++)
	{
		int i, id, maxl = 0, sum = 0, lpos = 0, ed;
		for(i = st, id = 1; i + 2 <= n; i += 3, id ++)
		{
			c[id] = calc(i);
			sum += c[id];
			l[id] = l[id - 1] + 3 * A;
			if(sum - l[id] > maxl) maxl = sum - l[id], lpos = id;
		}
		i -= 3;
		id --;
		ed = i + 2;
		int rpos = id + 1, maxr = 0;
		sum = 0;
		for(; i >= st; i -= 3, id --)
		{
			sum += c[id];
			r[id] = r[id + 1] + 3 * B;
			if(sum - r[id] > maxr) maxr = sum - r[id], rpos = id;
		}
		if(lpos >= rpos) ans = min(ans, min(A, B) * n);
		else ans = min(ans, sum - maxl - maxr + A * (st - 1) + B * (n - ed));
	}
	cout << ans;
	return 0;
}
posted @ 2026-02-25 16:59  yuzihang  阅读(15)  评论(0)    收藏  举报