CF1442A Extreme Subtraction

给出一个数列\(a_i\),每次可以将一段前缀或一段后缀减一,问是否可以变成全\(0\)

\(n\le 3*10^4\)


显然这相当于将\(a_i\)拆成\(x_i+y_i\),满足\(x_i\)不递减,\(y_i\)不递增。

从后往前钦定\(x_i\)的值,记变量\(pre\)表示当前钦定到的最小值,初值为无限大。如果\(a_i<pre\)\(a_i\)替换\(pre\);否则将\(a_i\)调整为\(pre\),并且将\([1,i]\)区间同时减\(a_i-pre\)。按照这个策略,如果不出现负数就合法。

这个策略让当前\(x_i\)最大,并且\(y_i\)最小,给后面的区间预留了更多的空间,所以是对的。


using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 30005
#define INF 1000000
#define ll long long
int n;
int a[N];
int main(){
//	freopen("in.txt","r",stdin);
	int T;
	scanf("%d",&T);
	while (T--){
		scanf("%d",&n);
		for (int i=1;i<=n;++i)
			scanf("%d",&a[i]);
		if (n==1){
			printf("YES\n");
			continue;
		}
		int pre=INF,cut=0;
		bool bz=1;
		for (int i=n;i>=1 && bz;--i){
			a[i]-=cut;
			if (a[i]<0)
				bz=0;
			if (a[i]<=pre)
				pre=a[i];
			else{
				cut+=a[i]-pre;
				a[i]=pre;
			}
		}
		if (bz)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}
posted @ 2020-11-03 07:30  jz_597  阅读(172)  评论(0编辑  收藏  举报