题解 ARC153C【± Increasing Sequence】

考虑调整。

首先,令 \(x=[1,2,\cdots,n]\) 可以计算出所求 \(S=\sum\limits_{i=1}^na_ix_i\)。如果 \(S\ne 0\),则需要对数列 \(x\) 进行调整。

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

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

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

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

\(S < 0\) 的情况同理。

时间复杂度 \(\Theta(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 @ 2023-01-16 15:39  rui_er  阅读(81)  评论(0编辑  收藏  举报