题干:
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, ..., aNindicating 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 6and 7.
题目大意:
给定一个长度为n的数列,初始时数列内数字都为0。
有一个操作,可以将数列中连续的长度为3、4或5的子数列中的数字全部+1。
问多次操作后能不能将数列变成输入的数列。
输入第一行包含一个正整数T(1<=T<=100),表示样例组数。
接下来2T行,其中第i行一个数字N(1<=N<=2*10^5)表示数列长度,第i+1行N个数字(0<=a<=10^9)表示最终要变成的数列;
所有N的和不超过4e6.
解题报告:
这题有一个巧妙的地方,也就是,如果你可以将连续长度为3,4,5的子数列的数字都+1,那么这就等价于你可以将任意长度>=3的所有子数列都+1。
所以我们可以求出差分数组,然后枚举每一个>0的数字,然后将它变为0,代价就是将后面从3个字符开始,找到最近的负数,都+上对应的一个数使之变成0.这样操作一遍然后check数组中是否有负数,如果有的话那就GG,否则就是Yes。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
int a[MAX],d[MAX],n;
int main()
{int t,iCase=0;cin>>t;while(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++) d[i] = a[i] - a[i-1];int cur = 4,flag = 1;for(int i = 1; i<=n-2; i++) {if(d[i] <= 0) continue; cur = max(cur,i+3);while(d[cur] >= 0 && cur <= n+1) cur++;while(cur <= n+1 && d[i] > 0) {while(d[cur] >= 0 && cur <= n+1) cur++;if(cur > n+1) break;int dc = min(d[i],-d[cur]);//absd[i] -= dc;d[cur] += dc;}if(d[i] > 0) {flag = 0;break;}//这句加不加都可以 想想为什么}for(int i = 1; i<=n+1; i++) {if(d[i] < 0) flag = 0;}if(flag == 1) printf("Case #%d: Yes\n",++iCase);else printf("Case #%d: No\n",++iCase);}return 0 ;
}
对于上面代码中的那个疑惑,其实不难想出,因为我们已经假设,这个序列是左边+1右边-1这样操作最后得到的这样一个序列,所以我们不难发现+1的数量和-1的数量应该是相同的,所以不会出现+1的数量过多,导致后面没有-1可以供选择这样的情况发生。