Codeforces Contest 1138 problem B Circus —— 死亡1700,暴力

Polycarp is a head of a circus troupe. There are n — an even number — artists in the troupe. It is known whether the i-th artist can perform as a clown (if yes, then ci=1, otherwise ci=0), and whether they can perform as an acrobat (if yes, then ai=1, otherwise ai=0).

Split the artists into two performances in such a way that:

each artist plays in exactly one performance,
the number of artists in the two performances is equal (i.e. equal to n2),
the number of artists that can perform as clowns in the first performance is the same as the number of artists that can perform as acrobats in the second performance.
Input
The first line contains a single integer n (2≤n≤5000, n is even) — the number of artists in the troupe.

The second line contains n digits c1c2…cn, the i-th of which is equal to 1 if the i-th artist can perform as a clown, and 0 otherwise.

The third line contains n digits a1a2…an, the i-th of which is equal to 1, if the i-th artist can perform as an acrobat, and 0 otherwise.

Output
Print n2 distinct integers — the indices of the artists that should play in the first performance.

If there are multiple answers, print any.

If there is no solution, print a single integer −1.

Examples
inputCopy
4
0011
0101
outputCopy
1 4
inputCopy
6
000000
111111
outputCopy
-1
inputCopy
4
0011
1100
outputCopy
4 3
inputCopy
8
00100101
01111100
outputCopy
1 2 3 6
Note
In the first example, one of the possible divisions into two performances is as follows: in the first performance artists 1 and 4 should take part. Then the number of artists in the first performance who can perform as clowns is equal to 1. And the number of artists in the second performance who can perform as acrobats is 1 as well.

In the second example, the division is not possible.

In the third example, one of the possible divisions is as follows: in the first performance artists 3 and 4 should take part. Then in the first performance there are 2 artists who can perform as clowns. And the number of artists in the second performance who can perform as acrobats is 2 as well.

题意:

给你n个人的两种技能,1代表会,0代表不会。现在有两场演出,每场需要分配n/2个人,每个人只能去一场,让你输出第一场去的人使得在第一场会第一个技能的人的数量=第二场会第二个技能的人的数量。

题解:

我真的服了,这是B该有的难度吗?而且为什么每个1700难度对我都这么不友好?sun dog。
还是不要看我的代码了,去看别人的吧,我自己写留个纪念。
我设会第一个技能但不会第二个技能为oz:one zero 同理可得:zo,oo,zz
首先如果zo有0个且oz也是0个且oo有奇数个,那么不论怎么分配都不可能相等
然后如果zo的数量-zz的数量>oz的数量+oo的数量,或者相反。也就是说一边无论怎么拿,会这个的人数都比另一边大,那么也是不可能的。
之后要考虑oz.size()和zo.size()的大小,我是直接做小的。如果(int)zo.size()>(int)oz.size()

重点:size()的有关操作最好是强转之后做,否则会re

那么oz肯定全部要取,之后就是while一下,看看要取多少oo,然后这里还有一个判断,我举个栗子:

oo zo oz+oo(给oz的oo,一开始假设全都给zo)
3  4   4

如果oo让给oz一个
那么就变成

oo zo oz+oo
2  4  5

如果再给一个,那么oz+oo就比zo最终所拥有的1多了,但是这是不被允许的,因为我后面并没有把zo的1补回来的办法。那么就要numoo+(int)zo.size()>(int)oz.size()+res+1的时候才能给。
注意这时候oo和zo的1的数量比oz多,那么我们之后把一个zo给oz,这样的话zo+oo的1的数量就会-1,但是oz的1的数量并不会加!
最后只需要加上少掉的zz就可以了。

第二种情况oz>zo。这时候一开始都一样,只要翻转一下,但是注意最后输出不能输出刚才找的这些,因为它是第二场。如果输出了第二场的技能1的话,可能就不对了,因为我们最后还有消去oz的过程。那么我们要用一个vis记录一下那些是第二场的,最后输出的时候判一下即可。

#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
const int N=5e3+5;
int a[N],b[N];
vector<int>ans,zz,zo,oz,oo;
int vis[N];
int main()
{
    int n,sec=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%1d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        scanf("%1d",&b[i]);
        if(a[i]==0&&b[i]==0)
            zz.push_back(i);
        else if(a[i]==0&&b[i]==1)
            zo.push_back(i);
        else if(a[i]==1&&b[i]==0)
            oz.push_back(i);
        else if(a[i]==1&&b[i]==1)
            oo.push_back(i);
    }
    if((int)zo.size()==0&&(int)oz.size()==0&&((int)oo.size())%2==1)
        return 0*printf("-1\n");
    if((int)zo.size()-(int)zz.size()>(int)oz.size()+(int)oo.size()||(int)oz.size()-(int)zz.size()>(int)zo.size()+(int)oo.size())
        return 0*printf("-1\n");
    //if(n==4990)
        //printf("%d %d %d %d\n",zo.size(),oz.size(),zz.size(),oo.size());
    if((int)zo.size()>(int)oz.size())
    {
        int i=0;
        for(int i=0;i<(int)oz.size();i++)
            printf("%d ",oz[i]);
        int numoo=(int)oo.size(),res=0;
        while(numoo+(int)zo.size()>(int)oz.size()+res+1&&numoo)
        {
            numoo--;
            printf("%d ",oo[res++]);
        }
        while(numoo+(int)zo.size()>(int)oz.size()+res)
            printf("%d ",zo[i++]),res++;
        while(i<zo.size()&&oz.size()+res<n/2)
            printf("%d ",zz[i++]),res++;
    }

    else
    {
        int azo=0,aoz=0,aoo=0,azz=0;
        for(int i=0;i<(int)zo.size();i++)
            vis[zo[i]]=1,azo+=(a[zo[i]]==0&&b[zo[i]]==1);
        int numoo=oo.size(),res=0;
        while(numoo+(int)oz.size()>(int)zo.size()+res+1&&numoo)
        {
            numoo--;
            vis[oo[res++]]=1,aoo+=(a[oo[res-1]]==1&&b[oo[res-1]]==1);
        }
        int i=0;
        while(i<(int)oz.size()&&numoo+(int)oz.size()>(int)zo.size()+res)
            vis[oz[i++]]=1,res++,aoz+=(a[oz[0]]==1&&b[oz[0]]==1);
        //if(n==5000)
            //printf("%d\n",res);
        while((int)zo.size()+res<n/2)
            vis[zz[i]]=1,i++,res++,azz+=(a[zz[i-1]]==0&&b[zz[i-1]]==0);
        //if(n==4990)
            //printf("%d %d %d\n",azo+aoo+azz+aoz,azo+aoo,oz.size()-aoz+oo.size()-aoo);
        for(int i=1;i<=n;i++)
            if(!vis[i])
                printf("%d ",i);
    }
    printf("\n");
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值