1. 程式人生 > >101775J(2017 EC final)

101775J(2017 EC final)

題目連結:點選這裡

解題思路:

差分序列:b[i] = a[i] - a[i-1]

原序列為: 1 4 5 8 7 差分後: 1 3 1 3 -1 -7,多出來的以為可以看做0 - a[n].

差分序列的性質:前i項和等於原序列的a[i],這個很容易就能證明

如果要對一個區間的數都加上1,那麼就是a[l]++,a[r+1]--,之後求一下字首和就是當前位置更新後的值了.

那不是和差分序列的性質一樣嗎?

對於本題來說任意大於3的長度都能分解為若干個3-5的段,那麼在差分序列中值是負的說明他執行了更多的a[r+1]--,反之正的亦然.

對於負的考慮之前有沒有那麼的更新此時使得i這位置可以變成該負值,如果不能就是No

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 2e5 + 10;
int n,m,a[mx],b[mx];
int main()
{
	int t,ca = 1;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i=0;i<n;i++) scanf("%d",a+i);
		b[0] = a[0];
		a[n] = 0;
		for(int i=1;i<=n;i++) b[i] = a[i] - a[i-1];
		int flag = 1;
		if(b[1]<0||b[2]<0) flag = 0;
		else{
			ll sum = 0;
			for(int i=0;i<=n;i++){
				if(b[i]>0) sum += b[i];
				int p = i + 3;//大於三的長度可以任意分解成若干個3-5的段 
				if(p>n) break;
				if(b[p]<0) sum += b[p];
				if(sum<0) break;//如果是負的,說明b[p]沒有被清除掉,之後也不會被清除掉,所以No 
			}
			if(sum) flag = 0;
		} 
		printf("Case #%d: %s\n",ca++,flag?"Yes":"No");
	}
	return 0;
}