2022年1月24日学习总结

10:00~13:00

做一套英语四级试卷,记单词。

13:00~15:00

辅导妹妹高中数学英语。

16:00~20:30

第一题:

P7940

​​​​​​[B2] Alice Wins! (hard version)

AB 每队 2n2n 人正在玩石头剪刀布。A 队第 ii 个人出 a_iai​,B 队第 ii 个人出 b_ibi​。编号相同的人会对战。若 A 队赢则加一分,平不得分,输扣一分。你必须恰好改变每队 nn 个人的出拳方案,使得 A 队的得分最高。输出得分的最大值和任意一组构造方案。

本题中,我们用 11 代表石头,22 代表剪刀,33 代表布。

输入输出样例

输入 #1复制

1
1
1 2
1 2

输出 #1复制

2
1 1
2 2

说明/提示

Explanation

For the first test case, we can change a_2a2​ to 11 and b_1b1​ to 22. Then Team A can get 22 points. It can be proved that this is the maximum score that Team A can get.

Constraints

1\le T,n \le 10^5;\ 1\le a_i,b_i \le 31≤T,n≤105; 1≤ai​,bi​≤3. The sum of nn of all test cases \le 10^5≤105.

解题思路:比简单版的题目难在要恰好每个公司换n个人,那么我们将A公司不能赢的先变成赢了并记下每个公司换了几个人的出拳方案,剩下的次数将没换过的赢的情况全部换成另一种赢的情况就可以消耗掉每个公司一次,有可能B公司单独剩下一次,就需要找到之前A公司输掉但是改赢的情况将AB公司的出拳再此改变。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int t,n,a[200005],b[200005],c[200005],d[200005];
bool check(int x,int y)
{
    if(x==1&&y==2)return 1;
    if(x==2&&y==3)return 1;
    if(x==3&&y==1)return 1;
    return 0;
}
bool vis[200005];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int cnt=0,cntx=0,cnty=0;
        for(int i=1; i<=n*2; i++)
        {
            scanf("%d",a+i);
            c[i]=a[i];
            vis[i]=0;
        }
        for(int i=1; i<=n*2; i++)
        {
            scanf("%d",b+i);
            d[i]=b[i];
        }
        for(int i=1; i<=2*n; i++)
        {
            if(check(a[i],b[i]))continue;
            cnt++;
            if(cnt%2==1)
            {
                cntx++;
                c[i]=d[i]-1;
                if(c[i]==0)c[i]=3;
            }
            else
            {
                cnty++;
                d[i]=c[i]+1;
                if(d[i]==4)d[i]=1;
            }
            vis[i]=1;
        }
        for(int i=1; i<=2*n; i++)
        {
            if(vis[i])continue;
            if(cntx<n&&cnty<n)
            {
                c[i]+=1;
                if(c[i]==4)c[i]=1;
                d[i]+=1;
                if(d[i]==4)d[i]=1;
                cntx++,cnty++;
            }
            if(cntx==cnty&&cntx==n)break;
        }
        if(cnty<n)
        {
            for(int i=1; i<=n*2; i++)
            {
                if(vis[i])
                {
                    for(int j=1; j<=3; j++)
                    {
                        for(int k=1; k<=3; k++)
                            if(j!=a[i]&&k!=b[i]&&check(j,k))c[i]=j,d[i]=k;
                    }
                    break;
                }
            }
        }
        printf("%d\n",2*n);
        for(int i=1; i<=n*2; i++)printf("%d ",c[i]);
        printf("\n");
        for(int i=1; i<=n*2; i++)printf("%d ",d[i]);
        printf("\n");
    }
    return 0;
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值