[CF1680D]Dog Walking 题解
Analysis
首先,简化题意,设 \(s_i = \sum\limits_{k=1}^i a_i\),则题中要求的就是 \(\max\{s\}-\min\{s\}+1\)。
若设 \(s_l = \max\{s\},s_r=\min\{s\}\),则这个式子珂以化为 \(\operatorname{abs}(s_l-s_r)+1\)。
题中 \(n \le 3\times 10^3\),显然可以在 \(O(N^2)\) 的时间内枚举 \((l,r)\),求出这个式子。
先不考虑 \(s_n=0\) 的限制,让我们想想怎么求解。
因为我们要让这段区间中的数的和尽量大,那么显然区间中的所有 \(0\) 都要填成 \(k\) 或 \(-k\)。
统计一下原序列中 \(0\) 个数的前缀和,随便维护下就好了。
真正的问题是 \(s_n = 0\) 怎么满足。
发现这个条件其实就是让 \((l,r)\) 和这段区间外的数加起来和为 \(0\)。
那么取区间内和区间外的绝对值最大值中较小者即可。
(不好描述,看代码。)
时间复杂度 \(O(N^2)\)。
Code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e3 + 5;
typedef long long ll;
int n;
ll k,a[maxn],sum[maxn],d[maxn];
ll absll(ll x) {
return x > 0 ? x : -x;
}
int main() {
scanf("%d%lld",&n,&k);
for(int i = 1;i <= n;++ i)scanf("%lld",&a[i]);
for(int i = 1;i <= n;++ i) {
sum[i] = sum[i - 1] + a[i];
d[i] = d[i - 1] + (a[i] == 0);
}
if(absll(sum[n]) > d[n] * k) {
puts("-1");
return 0;
}
ll ans = -1;
for(int l = 1;l <= n;++ l) {
for(int r = l;r <= n;++ r) {
ll tot = sum[r] - sum[l - 1],cnt = d[r] - d[l - 1];
ll totl = sum[n] - tot,cntl = d[n] - cnt;
ans = max(ans , min(absll(tot + cnt * k) , absll(totl - cntl * k)));
ans = max(ans , min(absll(tot - cnt * k) , absll(totl + cntl * k)));
}
}
printf("%lld\n",ans + 1);//0 is included as well
return 0;
}
完结撒花✿✿ヽ(°▽°)ノ✿