欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2017 EC final J(差分)

程序员文章站 2022-07-12 17:14:27
...

题目

题意:有n种扑克牌,每种扑克牌有ai张,每次可以打出3到5张连续的牌作为顺子,问这副牌能不能用顺子全打出来.

思路:又差分序列的性质可知,对于序列a[i],求出差分序列b[i]=a[i]-a[i-1],差分序列前k项和sum[k]=a[k]。题目给出了a[1]……a[n],我们求出差分序列b[1]……b[n],令b[n+1]=0-a[n],那么最后的sum[n+1]=0.我们(条件允许)打出一个顺子(设其出牌的区间为【l,r】,那么b[l]要减一,b[r+1]要加一
)能这样做的条件是b[l]>0,b[r+1]<0且,sum[l]+b[r]>=0, 再结合区间长度必须大于3的要求即可出解,至于区间长度小于5不用管,因为任何一个长度大于5的区间都可以从3 、4 、5凑出来。

#include<cstdio>
using namespace std;
int cas,a[200005],b[200005],t,n;
int main(){
 scanf("%d",&t);
 while(t--){
  scanf("%d",&n);
  for(int i=1;i<=n;i++){
   scanf("%d",&a[i]);
   b[i]=a[i]-a[i-1];
  }
  b[n+1]=0-a[n];
  int f=1,sum=0,p;
  if(b[2]<0||b[3]<0) f=0;
  else{
   for(int i=1;i<=n+1;i++){
    if(b[i]>0) sum+=b[i];
    p=i+3;
    if(p>n+1) break;
    if(b[p]<0) sum+=b[p];
    if(sum<0) break;
   }
   if(sum!=0) f=0;
  }
  if(f)  printf("Case #%d: Yes\n",++cas);
  else  printf("Case #%d: No\n",++cas); 
 }
 return 0;
}