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;
}