T735849 白光 (light) 赛后题解
题目传送门
思路
因为每次只能熄灭最左侧或者最右侧,所以最后亮着的灯一定是连续的。
显然,如果要熄灭一段的灯,那么得比全部换灯的颜色的代价少。
显然,那些不能让最后亮着的灯的个数为 \(3\) 的倍数的边上的灯必须熄灭。(即至少共熄灭 \(n\ \%\ 3\) 盏两边的灯)
做法
枚举一定要熄灭掉前面 \(0\) 到 \(2\) 盏灯,进行贪心。
每 \(3\) 盏灯为一组,算出从可以留的第一盏灯与最后一盏灯开始全部换色与关掉的代价,进行比较。
找到两个位置 lpos 与 rpos,为满足从留的第一盏灯与最后一盏灯开始,关灯比换色的代价差最大的位置。
如果满足 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;
}
hello, I'm yuzihang, if you need to copy this, please quote this url: https://www.cnblogs.com/yuzihang/p/19634621

浙公网安备 33010602011771号