题解:CF1941B Rudolf and 121

题意

给出一个由 nn 个整数组成的数组 aa,元素的编号从 11nn。对于每一次操作,选择下标 ii,执行以下赋值操作。

ai1ai11a_{i−1}\gets a_{i−1}−1

aiai2a_{i}\gets a_{i}−2

ai+1ai+11a_{i+1}\gets a_{i+1}−1

是否可以用这个操作,使整个数组变为零。

思路

题目中的操作是修改 33 个元素的值,考虑对原序列差分。题目中的每一次操作就相当于将差分数组 bi1b_{i-1} 以及 bib_{i}11,将 bi+1b_{i+1}bi+2b_{i+2}11。最终的目标是使得 bb 变为全零。

那么对于任何一个 ii,如果 bi1b_{i-1} 是一个正数,那么就必须选择 ii 执行 bi1b_{i-1} 次操作,因为在 i1i-1 后只有 ii 还能减小 bi1b_{i-1} 的值,而且也只能进行 bi1b_{i-1} 次操作,因为在操作就会使 bi1b_{i-1} 变为负数。如果 bi1b_{i-1} 此时为负数,那么就不可能在让它变为正数了,所以不可以使整个 bb 数组变为零。

那么我们从 22n1n-1 遍历一遍所有 bib_{i} 然后按照刚刚的思路操作就可以了。

最后检查 bb 数组如果不全为零,那么就不可以使整个 bb 数组变为零。

Code

#include <iostream>
using namespace std;
const int N=1e5*2+10;
int a[N],b[N];
int n;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=n;i++) if(a[i]<0)
		{
			puts("NO");
			continue;
		}
		b[1]=a[1];
		for(int i=2;i<=n;i++) b[i]=a[i]-a[i-1];
		bool flag=0;
		for(int i=2;i<n;i++)
		{
			if(b[i-1]<0) break;
			b[i]-=b[i-1];
			b[i+2]+=b[i-1];
			b[i+1]+=b[i-1];
			b[i-1]-=b[i-1];
		}
		for(int i=1;i<=n;i++)
			if(b[i]!=0) flag=1;
		if(flag) puts("NO");
		else puts("YES");
	}
	return 0;
}
posted @ 2024-03-13 21:36  PM_pro  阅读(34)  评论(0)    收藏  举报  来源