有n个盒子摆成一排,每个盒子内都有ai个糖果。
现在你可以执行以下操作:
·你可以选择任意一个盒子,在选择的盒子内吃掉一个糖果。
对你的要求如下:
·任何m个相邻的盒子内糖果数量不能超过x个。
请问,实现要求的最少操作次数是多少?
第一行三个数字n, m, x(2 ≤ n,m ≤ 106,1 ≤ x ≤ 109)。
第二行n个数字(1 ≤ ai ≤ 109)。
输出一个操作数,代表实现要求的最少操作数。
3 2 3 2 1 2
0
2 1 2满足题目要求,任意相邻的两个数值之和均不超过3,所以不需要进行任何操作。
auto getnxt = [&](auto&&getnxt,int p)->int
{
if (nxt[p] == p - 1)return p;
nxt[p] = getnxt(getnxt, nxt[p]);
return nxt[p];
}; 似乎可以构造出最坏解,而且我不会证明复杂度,感性判断,每个袋子被访问的次数不会太多,就是这样! #include <cctype>
#include <cstdio>
#include <cstdint>
uint8_t buf[1 << 20], * p1, * p2;
#define gc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<20,stdin)),*p1++)
int readint() {
int k = 0, f = 1, c = gc();
for (; !isdigit(c); c = gc()) if (c == '-') f = -1;
for (; isdigit(c); c = gc()) k = k * 10 + (c ^ 48);
return k * f;
}
ll cd[1001000];
int nxt[1001000];
void solve()
{
int n = readint();
int m = readint();
ll x = readint();
ll ans = 0;
ll now = 0;
auto getnxt = [&](auto&&getnxt,int p)->int
{
if (nxt[p] == p - 1)return p;
nxt[p] = getnxt(getnxt, nxt[p]);
return nxt[p];
};
ffp(i, 1, n)
{
cd[i] = readint();
nxt[i] = i - 1;
now += cd[i];
now -= cd[max(i - m, 0)];
int p = i;
while(now > x)
{
ll sub = min((now - x), cd[p]);;
ans += sub;
now -=sub;
cd[p] -= sub;
p = getnxt(getnxt, p);
}
}
cout << ans << endl;
}