Codeforces Round #585 (Div.2)

A. 最大值就是先找需要黄牌少的再找多的,跟最大人数比较一下;最小值就是先每人拿最多-1个,剩下的可以罚出;

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a1,a2,k1,k2,n;scanf("%d%d%d%d%d",&a1,&a2,&k1,&k2,&n);
    int mn,mx,tmp,kk;
    if(k1>k2) {swap(k1,k2);swap(a1,a2);}
    int nn=n;
    tmp=nn/k1;kk=min(tmp,a1);mx=kk;
    nn-=kk*k1;mx+=min(nn/k2,a2);
    k1--;k2--;
    tmp=k1*a1+k2*a2;
    mn=max(0,n-tmp);
    printf("%d %d\n",mn,mx);
    return 0;
}

B.  维护一个前缀积,分别记录[1,i]中记录为正负的个数,相乘即为负,总数减去就是正;因为任取一段负任取一段正可以得到一段为负;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
int main()
{
    int n;scanf("%d",&n);
    int op=1;
    ll s1=0,s2=1;
    ll sum=1ll*n*(n+1)/2;
    for (int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        if(x<0) op*=-1; 
        if(op<0) s1++;else s2++;
    }
    printf("%lld %lld\n",s1*s2,sum-s1*s2);
    return 0;
}

C.记录下(a,b)和(b,a)的个数,和为奇数则不成立,两个同类交叉交换可以使得两个位置相同,如果两个的个数都是奇数,可以自己交换一个构造成两个都是偶数;

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int maxn=2e5+7;
char s[maxn],t[maxn];
int tag[maxn];
struct node{int a,b;};
vector<node> ans;
void rua()
{
    int n;scanf("%d",&n);
    scanf("%s",s+1);scanf("%s",t+1);
    int s1=0,s2=0;
    for (int i=1;i<=n;i++) 
    {
        if(s[i]=='a' && t[i]=='b') {s1++;tag[i]=1;}
        if(s[i]=='b' && t[i]=='a') {s2++;tag[i]=2;}
    }
    if((s1+s2)%2==1) {printf("-1\n");return;}
    if(s1%2==1)
    {
        for (int i=1;i<=n;i++) 
            if(tag[i]==1) {tag[i]=2;ans.pb({i,i});break;}
    }
    int kk=0;
    for (int i=1;i<=n;i++)
        if(tag[i]==1) 
        {
            if(!kk) kk=i;
            else {ans.pb({kk,i});kk=0;}
        }
    kk=0;
    for (int i=1;i<=n;i++)
        if(tag[i]==2) 
        {
            if(!kk) kk=i;
            else {ans.pb({kk,i});kk=0;}
        }
    printf("%d\n",(int)ans.size());
    for (auto i:ans) printf("%d %d\n",i.a,i.b);
    return;
}
int main()
{
    rua();
    return 0;
}

D.就 分类讨论吧就,也就只有两者都不相等才要想想;

如果s1>s2,那么此时如果a1>a2,显然先手赢,在大的那边填大的,永远不会相等;如果a1<a2,那么前2*a1步可以看作是无效的,因为无论先手在那边填了几,后手都可以在另一边填相同的数,这两步可以看作无效,那么这种情况就可以理解为s1>s2且只有右边可以填a2-a1个数,如果a2-a1是奇数,那么先手赢,否则的话,判断s1-s2==(a2-a1)/2*9,如果成立后手赢,否则先手赢,因为无论先手是什么,后手都可以构造一个9出来,为什么是9不是其他的呢,如果是7,先手出8或者9,那就没了;

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
char s[maxn];
bool check(int s1,int s2,int a1,int a2)
{
    if(a1>a2 || (a2-a1)%2==1) return 0;
    return (s1-s2==(a2-a1)/2*9); 
}
bool rua()
{
    int n;scanf("%d",&n);
    scanf("%s",s+1);
    int s1=0,s2=0,a1=0,a2=0;
    for (int i=1;i<=n/2;i++)
    {
        if(s[i]=='?') a1++;
        else s1+=(s[i]-'0');
    }
    for (int i=n/2+1;i<=n;i++)
    {
        if(s[i]=='?') a2++;
        else s2+=(s[i]-'0');
    }
    if(s1==s2 && a1==a2) return 1;
    if(s1==s2 && a1!=a2) return 0;
    if(s1!=s2 && a1==a2) return 0;
    if(s1>s2) return check(s1,s2,a1,a2);
    else if(s1<s2) return check(s2,s1,a2,a1);
}
int main()
{
    if(rua()) printf("Bicarp\n");
    else printf("Monocarp\n");
    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值