Day12 T1 少女觉

题目

在幽暗的地灵殿中,居住着一位少女,名为古明地觉。
据说,从来没有人敢踏入过那座地灵殿,因为人们恐惧于觉一族拥有的能力——读心。
掌控人心者,可控天下。
人的记忆可以被描述为一个黑块(B)与白块(W)的序列,其中情感值被定义为序列中黑块数量与白块数量之比。
小五口在发动读心术时,首先要解析人的记忆序列,因此,需要将序列分割为一些段,并且要求每一段记忆序列的情感值都相等。
下面给出两个例子:
BWWWBB -> BW + WWBB (Ratio=1:1)
WWWBBBWWWWWWWWWB -> WWWB + BBWWWWWW + WWWB (Ratio=3:1)
现在小五手上有一个人的记忆序列,她想要知道,如何将手中的记忆序列分成尽可能多的段呢?

输入

第一行包含一个正整数T,代表数据组数。
对于每一组测试数据,第一行包含一个正整数N。
接下来N行描述一个序列,每行包含一个正整数K和一个大写字母C,表示序列接下来有连续K个颜色为C的方块。

输出

对于每组测试数据输出一行一个正整数,表示最多分成的段数。

样例

输入 输出
3
3
1 B
3 W
2 B
4
3 W
3 B
9 W
1 B
2
2 W
3 W
2
3
5

数据范围

对于10%的数据,\(N\leqslant15\)
对于20%的数据,\(N\leqslant500\)
另有30%的数据,\(K=1\)
另有30%的数据,\(K\leqslant50\)
对于100%的数据,\(N\leqslant10^5\),序列长度不超过\(10^9\)
保证对于全部测试点,输入文件行数不超过\(2.5\times10^6\)

题解

  因为每一段记忆序列的情感值都相等,设为K,那么由合比性质我们很容易知道,整个序列的情感值也为K。
  一旦情感值确定下来了,我们的分割就很方便了。很容易想到,遍历一遍序列,每当情感值为K时就分割,然后重新统计W和B的数量,当情感值为K时再分割,如此反复。
  然而,如果我们直接扫一遍整个序列,\(10^9\)的长度可能会超时。
  由合比性质,我们可以知道,若干分割出的小序列拼起来之后的序列的情感值也为K。那么我们就可以由当前W(B)的数量计算出要达到K我们还需要多少B(W),而再次达到K的时候,我们就可以再分割出一个小序列。
  如果当前我们所遍历到的这一段,B(W)的数量可以满足在这一段的某个位置,情感值再次达到K,那么我们就可以再当前的这一段分割出一个小序列。如果计算出当前需要的不是整数个,那么说明以当前的W(B)的数量,我们无法让情感值达到K,也就无法再分割出一个小序列。
PS:此题解部分借鉴星星之火OIer的博客

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e5+10;
int rnd,n;

ll cal(ll x,ll a,ll b){//用于计算还需要多少B(W)
    //因为x*b可能爆int,而如果先除,因为无法确定a是哪一个的约数,有可能因为下取整而使答案错误,所以要开ll
    return (x*b)%a ? -1 : x*b/a;
}

int main(){
    // freopen("silly.in","r",stdin);
    // freopen("silly.out","w",stdout);
    scanf("%d",&rnd);
    while(rnd--){
        ll times[MAXN];
        char ch[MAXN][2];
        ll sumb=0,sumw=0;
        scanf("%d",&n);
        for(register int i=1;i<=n;i++){
            scanf("%lld %s",&times[i],&ch[i]);
            if(ch[i][0]=='B') sumb+=times[i];
            if(ch[i][0]=='W') sumw+=times[i];
        }
        if(!sumb || !sumw){//如果全是B或W,则可以分成序列长(sumb+sumw)段
            printf("%d\n",sumb+sumw);
            continue;
        }
        ll cntb=0,cntw=0;
        int ans=0;
        for(register int i=1;i<=n;i++){
            if(ch[i][0]=='B'){
                ll p=cal(cntw,sumw,sumb);
                if(p>cntb && p<=cntb+times[i]) ans++;
                cntb+=times[i];
            }
            if(ch[i][0]=='W'){
                ll p=cal(cntb,sumb,sumw);
                if(p>cntw && p<=cntw+times[i]) ans++;
                cntw+=times[i];
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2020-01-20 19:33  东方澂  阅读(119)  评论(0编辑  收藏  举报