gym 101775 J Straight Master (2017ECfinal)

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 
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");
	}
}

 

你可能感兴趣的:(gym 101775 J Straight Master (2017ECfinal))