AcWing 5539. 牛奶交换 整体思维+破环成链思想
5539. 牛奶交换 - AcWing题库
y老师的板书
如果是往右循环,且有左循环与之相对头,如图所示,则可以发现,右循环的最后一个和左循环的第一个不会损失,因为分别有其右边和或左边的为它补给,而两端(用红线圈出来的部分)的因为没有补给而损失。所以只需将每一个方向相同R或L的划分为一个整体,剔除不会损失的那一个,将整体中其他的与m取小即可算出每一个整体还剩多少,最后将每一个整体求和即可
const int N = 4e5 + 10;//两倍长度
LL n,m;
char s[N];
LL a[N];
void solve()
{
cin >> n >> m;
LL ans = 0;
for (int i = 1;i <= n;i ++) cin >> s[i];
for (int i = 1;i <= n;i ++) cin >> a[i],ans += a[i];
for (int i = 1;i <= n;i ++)
{
s[i + n] = s[i];
a[i + n] = a[i];
}
int k = 1;
while(k <= n && s[k] == s[k + 1]) k ++;
//找可以分开的点
if (k < n)//有切口时,计算损失;没有切口时不会损失而是会一直循环
{
for (int i = k + 1;i + n - 1<= 2 * n;i ++)
{
int j = i;
LL sum = 0;
while(j <= k + n && s[j] == s[i]) sum += a[j],j ++;
if (s[j - 1] == 'R') sum -= a[j - 1];
else sum -= a[i];
ans -= min(m,sum);
i = j - 1;//i++之后i就指向第一个不同的位置了
}
}
cout << ans << endl;
}