题解 ARC153C【± Increasing Sequence】

考虑调整。

首先,令 x=[1,2,,n] 可以计算出所求 S=i=1naixi。如果 S0,则需要对数列 x 进行调整。

调整 x 的方法无外乎前缀减或者后缀加,其他方法都会导致 x 不满足单调递增的要求。

如果 S>0,则需要将所求往小调。如果存在一个 a 的前缀和为正,或者存在一个 a 的后缀和为负,则我们一定可以通过上述两种调整 x 的方法将所求调小。

因为 a 的值域为 {1,1},可以证明如果存在一个 a 的前缀和为正,则一定存在一个 a 的前缀和为 1。因此对于前缀减操作,我们找到这个前缀和为 1 的前缀,将每个数减去 S 即可。同理,如果存在一个 a 的后缀和为负,则一定存在一个 a 的后缀和为 1,后缀加操作找到这个后缀,将每个数加上 S 即可。

如果不存在一个 a 的前缀和为正,且不存在一个 a 的后缀和为负,则显然无解。

S<0 的情况同理。

时间复杂度 Θ(n)

// Problem: C - ± Increasing Sequence
// Contest: AtCoder - AtCoder Regular Contest 153
// URL: https://atcoder.jp/contests/arc153/tasks/arc153_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(ll x=(y);x<=(z);x++)
#define per(x,y,z) for(ll x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;
const ll N = 2e5+5;

ll n, a[N], x[N], pre[N], suf[N];
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}

int main() {
	scanf("%lld", &n);
	rep(i, 1, n) scanf("%lld", &a[i]);
	rep(i, 1, n) x[i] = i;
	ll S = 0;
	rep(i, 1, n) S += a[i] * x[i];
	rep(i, 1, n) pre[i] = pre[i-1] + a[i];
	per(i, n, 1) suf[i] = suf[i+1] + a[i];
	if(S > 0) {
		ll ok = 0;
		rep(i, 1, n) {
			ok |= pre[i] > 0;
			ok |= suf[i] < 0;
		}
		if(!ok) return puts("No")&0;
		ll pos = 0;
		rep(i, 1, n) {
			if(pre[i] == 1) {
				pos = i;
				break;
			}
		}
		if(pos) rep(i, 1, pos) x[i] -= S;
		else {
			per(i, n, 1) {
				if(suf[i] == -1) {
					pos = i;
					break;
				}
			}
			rep(i, pos, n) x[i] += S;
		}
	}
	else if(S < 0) {
		ll ok = 0;
		rep(i, 1, n) {
			ok |= pre[i] < 0;
			ok |= suf[i] > 0;
		}
		if(!ok) return puts("No")&0;
		ll pos = 0;
		rep(i, 1, n) {
			if(pre[i] == -1) {
				pos = i;
				break;
			}
		}
		if(pos) rep(i, 1, pos) x[i] -= -S;
		else {
			per(i, n, 1) {
				if(suf[i] == 1) {
					pos = i;
					break;
				}
			}
			rep(i, pos, n) x[i] += -S;
		}
	}
	puts("Yes");
	rep(i, 1, n) printf("%lld%c", x[i], " \n"[i==n]);
	return 0;
}
posted @   rui_er  阅读(107)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示