1. 程式人生 > >Straight Master Gym-101775J (思維+差分)

Straight Master Gym-101775J (思維+差分)

mas 差分 esp turn open sum ++i online master

題意:給出N種類的數量,求是否可以把N種牌按3-5張連續的順子打出,順子必須連續.
分析:相當於把這個序列分成若幹長度為[3,5]的區間,當然其實分成若幹段大於3的區間即可.因為大於5的區間又可以分拆成若幹段長度為[3,5]的區間.
\(b[i] = a[i] - a[i-1]\), 則\(b[i] >0\) 表示有\(b[i]\)段區間以此為起點, \(b[i] < 0\)表示有\(|b[i]|\)段區間以\(i-1\)為終點. 那麽對於每個區間的起點i,必須在i+3開始的位置一直向後尋找終點,且起點和終點必須數量相等,若不相等則不能打出順子.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 2e5+5; 
LL a[MAXN], b[MAXN];
int N;

bool check()
{
    LL sum = 0;
    if(b[2] <0 || b[3]<0) return false;
    for(int i=1;i<=N+1;++i){
        int p = i + 3;
        if(b[i] > 0) sum += b[i];
        if(p > N+1) break;
        if(b[p]<0 ){
            sum += b[p];
            b[p] = 0;
        }
        if(sum<0) break;
    }
    if(sum !=0) return false;
    return true;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
    int T,cas=1; scanf("%d",&T);
    while(T--){
        scanf("%d", &N);
        for(int i=1;i<=N;++i){
            scanf("%lld", &a[i]);
            b[i] = a[i] - a[i-1];
        }
        b[N+1] = -a[N];

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

Straight Master Gym-101775J (思維+差分)