2020 CCPC Wannafly Winter Camp Day5 A Alternative Accounts(二进制)

在这里插入图片描述

题意:

n n 个账号,其中某些账号参加了比赛。
比赛共 k k 场,每场比赛都以整数 m m 和一个长度为 m m 的序列 x x 描述。
序列 x x 的第 i i x x 表示参加了这场比赛的 m m 个账号。
参赛者不能使用不同账号参加同一场比赛。
一个账号只能属于一个参赛者。
在不违背前两条规则的前提下参加不同比赛的不同账号可属于同一个参赛者。
求最少有多少人参加了比赛。

注意到 k < 3 k<3 的情况被包含在 k = 3 k=3 的情况中。
只考虑 k = 3 k=3 的情况,模拟一下即可。
统计每个账号参加的比赛场数,并记下参加了哪几场比赛,则:

  • 参加比赛场数为 0 0 的账号没有影响。
  • 参加比赛场数为 2 3 \frac{2}{3} 的账号必定确定一个参赛者。
  • 参加比赛场数为 1 1 的账号,在不冲突的前提下可和参加比赛场数为 2 2 的账号同属一个参赛者。 剩下的只有参加比赛场数为 1 1
    的未匹配的账号,设共 t t 个。

按参加的比赛分类,假设最多的一类有 s s 个,则再有 max ( s , t s ) \max\left(s,t-s\right) 个参赛者即可。

AC代码:

const int N = 1e5 + 5;
int sum;
int cas = 0;
int n, m, k, x;
int ans, a[3], b[3], cnt[N], res[N];
int main()
{
    sdd(n, k);
    rep(i, 0, k - 1)
    {
        sd(m);
        rep(j, 1, m)
        {
            sd(x);
            cnt[x]++;
            res[x] |= 1 << i;
        }
    }
    rep(i, 1, n)
    {
        if (!cnt[i] || cnt[i] == 3 && ++ans)
            continue;
        for (int j = 0; j < 3 && cnt[i] > 1; j++)
            b[j] += !((res[i] >> j) & 1);
        for (int j = 0; j < 3 && cnt[i] < 2; j++)
            a[j] += (res[i] >> j) & 1;
    }
    rep(i, 0, 2)
    {
        ans += b[i];
        a[i] -= min(a[i], b[i]);
    }
    sort(a, a + 3);
    printf("%d\n", ans + max(a[2], a[0] + a[1]));
    return 0;
}
发布了704 篇原创文章 · 获赞 420 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/qq_43627087/article/details/104519334