luogu3615 如厕计划题解

原题地址:https://www.luogu.org/problem/show?pid=3615

题目数据范围较大,将所有字串连接为一个字串处理会超时。所以每个字串处理完后根据字串情况进行统计。
可以发现,题目有三种情况
1、男生人数大于》n,这正情况下是-1;
2、男女生人数相等,
3、女生人数大于男生人数。
首先考虑正序,遇到女生+1,遇到男生-1,那么在人数相等的情况下,前面的女生多了,就需要将其向后调整。所以记录女生比男生多出的人数最大值ans,结果就是ans-1.
如果女生人数比男生人数多,那么前面的男女共用厕所可以排更多的女生,可以排多少呢?设男生人数为cnt,那么男生用男女共用厕所的人数是cnt,剩下的n-cnt个厕位是女生可以用的,加上同时在用女厕的人数,所以女生比男生多2*(n-cnt)个,所以有ans-1-2*(n-cnt).也就是相当于将多的女生拿出来后,在男女生一样多的情况一样了。
代码修改自:ljm
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
long long ans=1,sum,n,m,x,l,p,q,cnt,maxp;
char s[233333];
int main()
{
    scanf("%lld%lld",&n,&m);
    for(long long i=1;i <= m;i++){
        for(long long k=1;s[k];s[k++]=0);
        scanf("%s%lld",s+1,&x);
        l = strlen(s+1);
		p = sum,q = cnt;maxp=-1;
        int fc=0,mc=0 ;
        for(long long i=1;i <= l;i++){
            sum += s[i] == 'F' ? 1 : -1, ans = max(ans,sum);
            if(s[i] == 'M')cnt++,fc++;
            else {
            	mc++;
            	if(sum==ans)maxp=i;            	
	    }   
        }
        cnt += (cnt-q)*(x-1);
        sum += (sum-p)*(x-1);
        if(maxp!=-1&&mc>fc)ans+=(mc-fc)*(x-1);
        ans = max(ans,sum);
    } 
    if(cnt > n)puts("-1\n");
    else
        printf("%lld\n",max((long long)0,ans-1-2*(n-cnt)));
    return 0;
}



也可以考虑逆序,经过上面的分析,我们发现,在女生大于男生的情况下,排在后面的男生不能在最后连续排列, ,所以我们只需要从后向前记录,假设男生为+1,女生为-1,那么记录男生的最大值即可。
代码参考洛谷题解。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
#define maxn 100005
int m;
long long sum,ans,sM,sF,k[maxn],n;
string s[maxn];

int main()
{
    ios::sync_with_stdio(false);  
    cin.tie(0);
    cin>>n>>m;
    for (int i=1;i<=m;i++) cin>>s[i]>>k[i];
    for (int i=m;i>=1;i--) 
    {
        int len=s[i].length();
        long long w1=0,w2=0,cntM=0,cntF=0;
        for (int j=len-1;j>=0;j--)
        {
            if (s[i][j]=='M') w1++,cntM++;else w1--,cntF++;
            ans=max(ans,w1+sum);
        }
        sM+=k[i]*cntM;sF+=k[i]*cntF;
        for (int j=len-1;j>=0;j--)        
            ans=max(ans,w1*k[i]+sum);
        sum=sum+w1*k[i];
    }
    if (sM>sF) cout<<"-1"<<endl;
    else cout<<max(ans-1,0ll)<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值