ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces 1680D. Dog Walking

2022-05-26 13:04:38  阅读:200  来源: 互联网

标签:Walking const LL mi Codeforces using mx 1680D define


传送门
\(\texttt{Difficulty:2400}\)

题目大意

一个长为 \(n(1\le n\le3000)\) 的序列 \(a(-10^9\le a_i\le10^9)\) ,可以用 \([-k,k](1\le k\le10^9)\) 的任意一个整数替换 \(a\) 中值为 \(0\) 的元素,求从 \(0\) 开始沿数轴移动,第 \(i\) 次移动的距离为 \(|a_i|\) (\(a_i<0\) 时向左,否则向右),并且最后能够回到 \(0\) 的过程中,能访问的整数点数量的最大值。

思路

对于整个移动过程,记在左侧能走到的最远点的值为 \(mi\) ,右侧能走到的最远点的值为 \(mx\) ,所能访问的整数点数量的最大值就是 \(mx-mi+1\) 。
在整个移动的过程中,我们采取的策略应当是先尽可能向左(右)走,再尽可能向右(左)走,最后回到 \(0\) ,这样能使得相互被抵消的部分尽可能少,于是我们可以枚举过程中的这两个分界点 \(i\), \(j\) ,假设我们先向左后向右,相当于我们在 \(i\) 处取 \(mi\) ,在 \(j\) 处取 \(mx\) ,那么我们在前 \(i\) 步的 \(0\) 中尽可能靠前填大的负数。在第 \([i+1,j]\) 步靠前填尽可能大的正数,此外还要保证最后能够回到 \(0\) ,即要保证左侧走到 \(mi\) 后右侧至少可以走回 \(0\) ,右侧走到 \(mx\) 也至少可以走回 \(0\) 。我们可以在一开始先预处理出序列 \(a\) 的前缀和以及其含有 \(0\) 的个数的前缀和,于是对于每次枚举,我们可以在 \(O(1)\) 求出满足上述条件下的 \(mi\) 与 \(mx\) ,也就是当前情况下的答案,最后将两种策略都分别枚举一遍取 \(\texttt{min}\) 即可,总的复杂度 \(O(n^2)\) 。

代码

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
using PII = pair<int, int>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
#define mk make_pair
//#define int LL
//#define lc p*2
//#define rc p*2+1
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-8;
const LL MOD = 1000000007;
const LL mod = 998244353;
const int maxn = 3010;

LL N, K, A[maxn], S[maxn], SS[maxn];

void solve()
{
	LL sum = 0;
	for (int i = 1; i <= N; i++)
		sum += A[i], S[i] = S[i - 1] + (A[i] == 0), SS[i] = SS[i - 1] + A[i];
	LL lst = 0LL - sum, ans = 1;
	if (lst > S[N] * K || lst < S[N] * -K)
	{
		cout << -1 << endl;
		return;
	}
	for (int i = 0; i <= N; i++)
	{
		for (int j = i + 1; j <= N; j++)
		{
			LL sub = min(K * S[i], K * (S[N] - S[i]) - lst), mi = SS[i] - sub;
			LL add = min(K * (S[j] - S[i]), K * (S[N] - S[j]) + lst + sub), mx = SS[j] - sub + add;
			ans = max(ans, mx - mi + 1);
		}
	}
	for (int i = 0; i <= N; i++)
	{
		for (int j = i + 1; j <= N; j++)
		{
			LL add = min(K * S[i], K * (S[N] - S[i]) + lst), mx = SS[i] + add;
			LL sub = min(K * (S[j] - S[i]), K * (S[N] - S[j]) - lst + add), mi = SS[j] - sub + add;
			ans = max(ans, mx - mi + 1);
		}
	}
	cout << ans << endl;
}

int main()
{
	IOS;
	cin >> N >> K;
	for (int i = 1; i <= N; i++)
		cin >> A[i];
	solve();

	return 0;
}

标签:Walking,const,LL,mi,Codeforces,using,mx,1680D,define
来源: https://www.cnblogs.com/Prgl/p/16313049.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有