Straight Master Gym - 101775J (差分)

A straight is a poker hand containing five cards of sequential rank, not necessarily to be the same suit. For example, a hand containing 7 club, 6 spade, 5 spade, 4 heart and 3 diamond forms a straight. In this problem, we extend the definition of a straight to allow 3 to 5 cards of sequential rank. Hence a hand containing K spade, Q club, and J heart is also a straight.

Mr. Panda is playing a poker game called Straight Master. The game uses a large deck of card that has N ranks from 1 to N. The rule of the game is simple: split the cards in Mr. Panda's hand into several straights of length from 3 to 5.

Now given a hand of cards, can you help Mr. Panda to determine if it is possible to split the cards into straights?

Input

The first line of the input gives the number of test cases, T. T test cases follow.

Each test case contains two lines. The first line contains an integer N, indicating the number of ranks in the deck. The next line contains N integers a1, a2, ..., aN indicating the number of cards for each rank in Mr. Panda's hand.

  • 1 ≤ T ≤ 100.
  • 1 ≤ N ≤ 2 × 105.
  • 0 ≤ ai ≤ 109.
  • .

Output

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is Yes if Mr. Panda can split all his cards into straights of length from 3 to 5, or No otherwise.

Example

Input

2
13
1 2 2 1 0 0 0 0 0 0 0 0 0
13
1 1 1 1 0 1 1 0 0 0 0 0 0

Output

Case #1: Yes
Case #2: No

Note

In the first test case, Mr. Panda can split his cards into two straights: [1, 2, 3] and [2, 3, 4]. In the second test case, there is no way to form a straight for card 6 and 7.

 

 

差分就是将数列中的每一项分别与前一项数做差,例如:

一个序列1 2 5 4 7 3,差分后得到1 1 3 -1 3 -4 -3

这里注意得到的差分序列第一个数和原来的第一个数一样(相当于第一个数减0)

差分序列最后比原序列多一个数(相当于0减最后一个数)

性质:

1、差分序列求前缀和可得原序列

2、将原序列区间[L,R]中的元素全部+1,可以转化操作为差分序列L处+1,R+1处-1

3、按照性质2得到,每次修改原序列一个区间+1,那么每次差分序列修改处增加的和减少的相同

上文转载自这里

 

首先由于互质,可以知道他们一定能组合成所有的>=3的所有数,换句话,也就是可以消掉大于等于3的段。

所以题目就是问我们可不可以找到一种方案,使得每一段都是 \geq 3 的。

差分数列比较好,我们也看到了他的性质,我们只需要考虑端点就好了。

我们可不可以从全0的数列,变成所求的数列。 考虑每一段都是 【+1,-1】,所以也就是 看看可不可以把所有的正负相消,

当然长度必须\geq 3。 实现的话,想想贪心,肯定是 左边正数的和左边的负数结合,这样才能最大匹配。 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=b-1;i>=a;--i)

const int N=2e5+10;

LL val[N],dif[N];
int check(int n){
	int ok=1;
	int r=1;  LL sum=0;
	for(int i=1;i<=n;i++){
		if(dif[i]<=0)continue;
		if(r-i<3){
			if(sum!=0){
				//printf("***i:%d\n",i);
				ok=0;break;
			}
		}
		sum+=dif[i];
		//printf("sum:%lld r:%d\n",sum,r);
		while(r<=n&&sum>=0){
			r++;//把++ 放在前面,这样就是正好的位置了
			if(r<=n&&dif[r]<0){
				if(r-i<3)ok=0;
				sum+=dif[r];
			}
			//printf("sum:%lld r:%d\n",sum,r);
		}
		//printf("i:%d r:%d sum:%lld\n",i,r,sum);
		if(sum>0)ok=0;
		if(!ok)break;
	}
	if(sum!=0)ok=0;
	//printf("sum:%lld ok:%d\n",sum,ok);
	return ok;
}


int main()
{
	int T;
	scanf("%d",&T);
	rep(kase,0,T){
		int n;
		scanf("%d",&n);
		rep(i,1,n+1){
			scanf("%lld",&val[i]);
			dif[i]=val[i]-val[i-1];
		}
		dif[n+1]=-val[n];

		//dif[n+2]=0;

		//rep(i,1,n+2)printf("i:%d %lld\n",i,dif[i]);

		if(check(n+1))
			printf("Case #%d: Yes\n",kase+1);
		else
			printf("Case #%d: No\n",kase+1);
	}
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值