[CF1680D]Dog Walking 题解

传送门QAQ

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;
}

完结撒花✿✿ヽ(°▽°)ノ✿

posted @ 2022-07-08 18:27  ImALAS  阅读(77)  评论(0编辑  收藏  举报