101775J Straight Master (差分)
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.
題意:
有n種撲克牌,每種撲克牌有ai張,每次可以打出3到5張連續的牌作為順子,問這副牌能不能用順子全打出來。
差分:
差分就是將一串數分別於前一個數做差,例如:
一個序列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,那麼每次差分序列修改處增加的和減少的相同
思路:
換一個思路,給定一個長度為0的序列,每次可以選擇長度為3,4,5的區間並將這個區間內的數全部加一,最終可以得到一個新的序列,問這個序列的每個數分別是多少,這個序列就是給定的n種撲克牌。
對於這個問題,可以用差分的思想,對於區間[L, R],可以開一個新的陣列b,這個區間加一後可以認為是b[L]+=1, b[R+1]-=1, b的字首和即為對應的數字。
原來那個問題就可以轉化為給你一個序列,問這個序列可不可以由上面的操作得到。也可以構建一個差分陣列b,其中b[i] = a[i]-a[i-1]。如果這個b陣列對於每個相鄰距離大於等於3的b[i] 和 b[j] (j>=i+3),如果每一對的和加起來等於0,則給定的數列是可以得到的,否則就無法得到。
程式碼:
#include <cstdio>
using namespace std;
const int MAXN = 200005;
int a[MAXN],b[MAXN];
int main(){
int T,N;
scanf("%d",&T);
for(int _=1 ; _<=T ; ++_){
scanf("%d",&N);
for(int i=1 ; i<=N ; ++i)scanf("%d",&a[i]);
a[N+1] = 0;
for(int i=1 ; i<=N+1 ; ++i)b[i] = a[i] - a[i-1];
bool flag = true;
if(b[1]<0 || b[2]<0 || b[3]<0)flag = false;
else {
long long sum = 0;
for(int i=1 ; i<=N+1 ; ++i){
if(b[i] > 0)sum += b[i];
int t = i + 3;
if(t > N+1)break;
if(b[t] < 0){
sum += b[t];
b[t] = 0;
}
if(sum < 0)break;
}
if(sum != 0)flag = false;
}
if(flag)printf("Case #%d: Yes\n",_);
else printf("Case #%d: No\n",_);
}
return 0;
}