欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

gym 101775 J Straight Master (2017ECfinal)

程序员文章站 2022-07-12 17:14:03
...

https://codeforces.com/gym/101775/problem/J

题意:给你一组目标序列,另外一组序列的初始值都是0,你每次可以将长度为3~5的区间整体加上一个1,现在问你最终能不能得到目标序列。

思路:首先一个结论就是对于一个长度大于5的区间我们可以分成任意[3,5]的区间,所以有了这个结论我们就可以把区间分成大于3的序列就好了,具体怎么做?我们对目标数组进行差分,可以得出,当某个位置i的差分数值大于0(记为c[i])的时候我们可以知道的是这个区间被加了几次(以i开头的区间有c[i]个),之后我们看他的i+3这个位置,如果他是小于0的话(也记为c[i])那么就代表了这个区间他被减去了几次(以i结尾的区间有c[i]个),之后我们将大于0的和小于0的相加看看最后的值是不是等于0,还有一种情况就是,他的sum每次都要大于等于0,倘若他小于0了就表示他在此之前有一个没有被匹配上。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
long long a[maxn] , b[maxn];
int main()
{
	int t;
	scanf("%d",&t);
	for(int T = 1 ; T <= t ; T++)
	{
		memset(b,0,sizeof(b));
		int n;
		scanf("%d",&n);
		for(int i = 1 ; i <= n ; i++) scanf("%lld",&a[i]);
		a[n+1] = 0;
		long long sum = 0;
		for(int i = 1 ; i <= n + 1 ; i++) b[i] = a[i] - a[i-1];
		if(b[2] < 0 || b[3] < 0) sum = maxn;
		else 
		{
			for(int i = 1 ; i <= n + 1 ; i++)
			{
				if(b[i] >= 0) sum += b[i];
				int p = i + 3 ;
				if(p > n + 1) break;
				if(b[p] < 0) sum += b[p];
				if(sum < 0) break;
			}
		}
		
		printf("Case #%d: ",T);
		if(sum != 0) puts("No");
		else puts("Yes");
	}
}