整数分组

整数分组

给定一个包含 n 个整数 s1,s2,,sn 的集合 S

我们规定,如果某个整数在一个集合中恰好出现一次,则称该整数为超级数。

例如,集合 {1,1,2,3,3,3,4} 中包含两个超级数 2,4

现在,请你将 S 分成两个集合 AB(其中一个可以为空),使得集合 A 中超级数的数量与集合 B 中超级数的数量相同(也就是说,集合 A 中恰好出现一次的整数的数量与集合 B 中恰好出现一次的整数的数量相同)。

输入格式

第一行包含一个整数 n

第二行包含 n 个整数 s1,s2,,sn

输出格式

如果不存在合理的划分方案,则输出一行 NO 。

否则,第一行输出 YES ,第二行输出一个长度为 n 的由 A 和 B 构成的字符串,其中的第 i 个字符,如果为 A 则表示 si 划分到集合 A,如果为 B 则表示 si 划分到集合 B

如果方案不唯一,输出任意合理方案均可。

数据范围

6 个测试点满足 2n12
所有测试点满足 2n1001si100

输入样例1:

4
3 5 7 1

输出样例1:

YES
BABA

输入样例2:

3
3 5 1

输出样例2:

NO

 

解题思路

  这题还是比较容易想到的,不过比赛的时候比较紧张,代码写得又长又臭。这一题的细节还是比较多的。

  先扫描一遍序列,统计只出现过一次的数的个数,假设是k,分情况讨论:

  1. 2k,那么两个集合每个都分k2个就可以了,剩余数的出现次数都大于1,可以将他们全部放到AB中。最后就可以实现两个集合的超级数的数量都是k2
  2. 2k,那么一个集合分k2个,另外一个集合分k2+1个。然后看一下剩余的数,如果某个数x出现了2次,那么无论怎么放x,都不能使得某个集合的超级数个数增加1个(全部x放到某个集合或两个集合各放一个x),因此如果某个数出现了2次那么这个数没有意义。如果某个数x出现超过2次,那么把一个x放到某个集合中,剩余的x都放到另外一个集合中,那么就可以使得只放一个x的那个集合的超级数个数加1。因此如果k是奇数,分完了超级数后某个集合的超级数个数少了一个,此时如果存在某个数的出现次数大于2,那么都可以构造一个合法方案,而如果剩余数的出现次数都是2的话则无解。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 110;
 5 
 6 vector<int> p[N];
 7 
 8 int main() {
 9     int n;
10     cin >> n;
11     for (int i = 0; i < n; i++) {
12         int x;
13         cin >> x;
14         p[x].push_back(i);
15     }
16     
17     int cnt = 0;
18     for (int i = 0; i < N; i++) {
19         if (p[i].size() == 1) cnt++;    // 统计出现次数为1的数的个数
20     }
21     
22     string ret(n, 'A'); // 初始化每个数都在集合A中
23     for (int i = 0, k = 0; i < N; i++) {
24         if (p[i].size() == 1 && k < cnt >> 1) { // 前k/2个数放到集合B中,如果cnt是奇数那么最后集合B的超级数比A少1
25             ret[p[i][0]] = 'B';
26             k++;
27         }
28     }
29     
30     bool flag = true;
31     if (cnt & 1) {  // 超级数的个数为奇数
32         flag = false;
33         for (int i = 0; i < N; i++) {
34             if (p[i].size() > 2) {  // 找到某个数的出现次数大于2
35                 ret[p[i][0]] = 'B'; // 取第一个数放到集合B中,剩余的都放到集合A
36                 flag = true;
37                 break;
38             }
39         }
40     }
41     
42     if (flag) cout << "YES\n" << ret;
43     else cout << "NO";
44     
45     return 0;
46 }
复制代码

 

参考资料

  AcWing 4608. 整数分组(AcWing杯 - 周赛):https://www.acwing.com/video/4274/

posted @   onlyblues  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示