Problem I - Bricks ACM/ICPC Central Europe Regional Contest 2014

这一题要求划分的block最多,所以从左往右遍历,只要当前一段的B and W符合ratio,划分成一个block即可。测试数据可能会有多个相连的B or W。如果当前位置W个数>0,可以算出需要多少B,如果个数不够,就看下一个位置能否补充足够的B。如果当前B的个数超出了需求量,一定无法保证ratio。如果当前位置B个数>0,可以算出需要多少W。这两种情况都需要判断,当both B,W>0时,可能只符合其中一种。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>

using namespace std;
//CERC 2014 Problem I Bricks
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int T;
int n;
long long ans;
pair<long long,char>line[maxn];
long long cntw;
long long cntb;
pair<long long,long long>rat;
long long quickgcd(long long a,long long b)
{
    if(a==0) return b;
    if(b==0) return a;
    if(!(a&1)&&!(b&1)) return quickgcd(a>>1,b>>1)<<1;
    else if(!(b&1)) return quickgcd(a,b>>1);
    else if(!(a&1)) return quickgcd(a>>1,b);
    else return quickgcd(abs(a-b),min(a,b));
}
void solve()
{
    long long w=0;
    long long b=0;
    for(int i=0;i<n;i++)
    {
        if(line[i].second=='W') w+=line[i].first;
        else if(line[i].second=='B') b+=line[i].first;
        //cout<<w<<" "<<b<<endl;
        if(w>0&&w%rat.first==0)
        {
            int tmp=w/rat.first*rat.second;
            if(b<=tmp)// continue; should not continue if b>tmp, might be applicable for the next if
            {
                if(b==tmp)
                {
                    ans++;
                    w=0;
                    b=0;
                    continue;
                }
                tmp-=b;
                if(line[i+1].second=='B'&&line[i+1].first>=tmp)
                {
                    line[i+1].first-=tmp;
                    ans++;
                    w=0;
                    b=0;
                    continue;
                }
            }

        }
        if(b>0&&b%rat.second==0)//should consider two if, might satisfy the second if only when both b,w>0
        {
            int tmp=b/rat.second*rat.first;
            if(w<=tmp) //continue;
            {
                if(w==tmp)
                {
                    ans++;
                    w=0;
                    b=0;
                    continue;
                }
                tmp-=w;
                if(line[i+1].second=='W'&&line[i+1].first>=tmp)
                {
                    line[i+1].first-=tmp;
                    ans++;
                    w=0;
                    b=0;
                    continue;
                }
            }

        }
    }
}
int main()
{
    freopen("all.in","r",stdin);
    freopen("myall.out","w",stdout);
    //freopen("input.txt","r",stdin);
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%d",&n);
        memset(line,0,sizeof(line));
        cntw=0;
        cntb=0;
        ans=0;
        long long cnt=0;
        char brick=' ';
        for(int i=0;i<n;i++)
        {
            scanf("%I64d %c",&cnt,&brick);
            line[i]=make_pair(cnt,brick);
            if(brick=='W') cntw+=cnt;
            else if(brick=='B') cntb+=cnt;
        }
        if(cntw==0)
        {
            //rat=make_pair(0,1);
            ans=cntb;
        }
        else if(cntb==0)
        {
            //rat=make_pair(1,0);
            ans=cntw;
        }
        else
        {
            int d=quickgcd(cntw,cntb);
            rat=make_pair(cntw/d,cntb/d);
            solve();
        }
//        if(ca==13797)
//        {
//            cout<<n<<endl;
//            for(int i=0;i<n;i++)
//            {
//                cout<<line[i].first<<" "<<line[i].second<<endl;
//            }
//        }
        //printf("Case #%d: %I64d\n",ca,ans);
        printf("%I64d\n",ans);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值