1. 程式人生 > >Straight Master Gym

Straight Master Gym

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