前言
哇这个坑爹题!!!考试时想不到正解,考试后知道了正解却打不对
啊啊啊啊
题目
在幽暗的地灵殿中,居住着一位少女,名为古明地觉。
据说,从来没有人敢踏入过那座地灵殿,因为人们恐惧于觉一族拥有的能力——读心。
掌控人心者,可控天下。
咳咳。
人的记忆可以被描述为一个黑块(B)与白块(W)的序列,其中情感值被定义为序列中黑块数量与白块数量之比。
小五口在发动读心术时,首先要解析人的记忆序列,因此,需要将序列分割为一些段,并且要求每一段记忆序列的情感值都相等。
下面给出两个例子:
BWWWBB -> BW + WWBB (Ratio=1:1)
WWWBBBWWWWWWWWWB -> WWWB + BBWWWWWW + WWWB (Ratio=3:1)
现在小五手上有一个人的记忆序列,她想要知道,如何将手中的记忆序列分成尽可能多的段呢?
Input
第一行包含一个正整数T,代表数据组数。
对于每一组测试数据,第一行包含一个正整数N。
接下来N行描述一个序列,每行包含一个正整数K和一个大写字母C,表示序列接下来有连续K个颜色为C的方块。
Output
对于每组测试数据输出一行一个正整数,表示最多分成的段数。
Sample Input
3 3 1 B 3 W 2 B 4 3 W 3 B 9 W 1 B 2 2 W 3 W
Sample Output
2 3 5
【数据范围】
对于10%的数据,n<=15
对于20%的数据,n<=500
另有30%的数据,K=1
另有30%的数据,K<=50
对于100%的数据,N<=10^5,序列长度不超过10^9
保证对于全部测试点,输入文件行数不超过2.5*10^6
分析
参考题解:https://www.cnblogs.com/xxzh/p/9885397.html
显然每一段的比例与全部的比例是一样的(考试的时候很智障地没看出来,所以卡住了),
那么我们先把全部的比例算出来,然后考虑加入每一段是否可能存在一个位置满足与全部的比例相同,如果有的话就ans++
注意考虑整个序列都是 B 或者都是 W 的情况
考试暴搜代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;//记得开ll
const int MAXN=1e7;
int preb[MAXN+5],prew[MAXN+5];
int t,n,k,cnt1,cnt2,tot,ans;
char c;
bool flag=true;
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
void dfs(int id,int lid,int b,int w,int cnt)//lid:last id
{
if(id>=tot)
return ;
int xb=preb[id]-preb[lid];
int xw=prew[id]-prew[lid];
int yb=preb[tot]-preb[id];
int yw=prew[tot]-prew[id];
//printf("id:%d lid:%d b:%d w:%d cnt:%d\n",id,lid,b,w,cnt);
//划开
if(xb*yw==xw*yb&&xb*w==xw*b&&yb*w==yw*b)
ans=max(ans,cnt+2);
dfs(id+1,id,xb/gcd(xb,xw),xw/gcd(xb,xw),cnt+1);
//不划开
xb=preb[tot]-preb[lid];
xw=prew[tot]-prew[lid];
if(xb*w==xw*b)
ans=max(ans,cnt+1);
dfs(id+1,lid,b,w,cnt);
}
void Init()
{
flag=true;
ans=cnt1=cnt2=0;
memset(preb,0,sizeof(preb));
memset(prew,0,sizeof(prew));
}
int main()
{
freopen("silly.in","r",stdin);
freopen("silly.out","w",stdout);
scanf("%d",&t);
while(t--)
{
Init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d %c",&k,&c);
if(c=='B')
{
for(int i=cnt1+cnt2+1;i<=cnt1+cnt2+k;i++)
{
preb[i]=preb[i-1]+1;
prew[i]=prew[i-1];
}
cnt1+=k;
}
else
{
for(int i=cnt1+cnt2+1;i<=cnt1+cnt2+k;i++)
{
prew[i]=prew[i-1]+1;
preb[i]=preb[i-1];
}
cnt2+=k;
}
if(k!=1)
flag=false;
}
tot=cnt1+cnt2;
if(!cnt1||!cnt2)
{
printf("%d",cnt1+cnt2);
continue;
}
if(flag)//k全是1:W,B间隔出现
{
if(cnt1==cnt2)
printf("%d",cnt1);
else
printf("1");
}
else
{
dfs(1,0,0,0,0);
printf("%d\n",ans);
}
}
return 0;
}
莫名其妙WA代码
#include<cstdio>
#include<vector>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int MAXN=1e7;
int t,n,k,cnt1,cnt2;
int ans,b,w;
char c;
vector<int> a;
int Cal(int x,int a,int b)
{
if(1LL*x*b%a!=0)
return -1;
return 1LL*x*b/a;
}
signed main()
{
freopen("silly.in","r",stdin);
freopen("silly.out","w",stdout);
scanf("%lld",&t);
while(t--)
{
ans=cnt1=cnt2=b=w=0;
a.clear();
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld %c",&k,&c);
if(c=='B')
{
cnt1+=k;
a.push_back(-k);
}
else
{
cnt2+=k;
a.push_back(k);
}
}
if(!cnt1||!cnt2)
{
printf("%lld\n",cnt1+cnt2);
continue;
}
int b=0,w=0,tmp;
for(int i=0;i<a.size();i++)
{
tmp=a[i];
if(tmp<0)//B
{
tmp=-tmp;
int p=Cal(w,cnt2,cnt1);
if(p>b&&p<=b+tmp)
ans++;
b+=tmp;
}
else//W
{
int p=Cal(b,cnt1,cnt2);
if(p>w&&p<=w+tmp)
ans++;
w+=tmp;
}
}
printf("%lld\n",ans);
}
return 0;
}
AC代码
#include<cstdio>
#include<vector>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int MAXN=1e7;
int t,n,k,cnt1,cnt2;
int ans,b,w;
char c;
vector<int> a;
int Cal(int x,int a,int b)
{
if(1LL*x*b%a!=0)
return -1;
return 1LL*x*b/a;
}
signed main()
{
//freopen("silly.in","r",stdin);
//freopen("silly.out","w",stdout);
scanf("%lld",&t);
while(t--)
{
ans=cnt1=cnt2=b=w=0;
a.clear();
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld %c",&k,&c);
if(c=='B')
{
cnt1+=k;
a.push_back(-k);
}
else
{
cnt2+=k;
a.push_back(k);
}
}
if(!cnt1||!cnt2)
{
printf("%lld\n",cnt1+cnt2);
continue;
}
int b=0,w=0,tmp;
for(int i=0;i<a.size();i++)
{
tmp=a[i];
if(tmp<0)//B
{
tmp=-tmp;
int p=Cal(w,cnt2,cnt1);
if(p>b&&p<=b+tmp)
ans++;
b+=tmp;
}
else//W
{
int p=Cal(b,cnt1,cnt2);
if(p>w&&p<=w+tmp)
ans++;
w+=tmp;
}
}
printf("%lld\n",ans);
}
return 0;
}
番外
不是很懂为什么一加就把整个段都加上了...
求好心人解答