CF1515D Phoenix and Socks (贪心 思维)

博客围绕Phoenix and Socks题目展开,给出大致题意,即有n只分左右且有颜色的袜子,可执行两种操作,求最少操作次数使袜子配对。解题采用贪心 + 思维方法,分析不同袜子情况的操作次数,还给出了不同数量左右袜子的处理思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接: Phoenix and Socks

大致题意

给你n只袜子, 有l只左袜子, r只右袜子. 每只袜子有颜色c.

你可以执行两种操作:
​ ① 左袜子变成右袜子, 右袜子变成左袜子
​ ② 把这个袜子改成任意一种颜色

问: 最少执行多少次操作, 使得n只袜子可以相互配对(一左一右, 且颜色相同)

解题思路

贪心 + 思维

首先我们明确一点, 如果此时我们都是一种类型的袜子(不妨认为是左袜子), 此时他们的颜色还都不一样, 那么我们必然需要操作2次, 才能使得袜子成功配对一对.

除此之外, 如果不同类型的袜子, 且颜色不同, 操作1次. 如果相同颜色且同类型袜子,操作1次.

到此, 我们的思路就已经有了, 对于本身已经配对的袜子, 我们直接移除不看即可.

对于余下的袜子, 假设有左袜子lnum双, 右袜子rnum双.
① 若lnum == rnum, 我们修改颜色使它们配对即可, 花费为lnum.

② 若lnum != rnum, 我们不妨假设左袜子多, 我们希望使得多余的部分左袜子, 如果把它变成右袜子, 直接可以配对. 这样我们可以避免操作2次的情况. 你会发现, 如果某种颜色的左袜子不止一双, 我们才可以通过1次操作使其配对.
当然我们也有可能仍会余下左袜子(最坏的情况就是左袜子每种颜色都是1只), 那我们不得不花费2次操作, 使得其配对.

代码方面还是有一些细节的, 处理好就可以快乐AC啦!

AC代码

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 2E5 + 10;
int l[N], r[N]; //记录每种颜色的左袜子/右袜子 只数.
int main()
{
	int t; cin >> t;
	while (t--) {
		int n, lnum, rnum; scanf("%d %d %d", &n, &lnum, &rnum);
		rep(i, n) l[i] = r[i] = 0;

		rep(i, lnum) {
			int x; scanf("%d", &x);
			l[x]++;
		}
		rep(i, rnum) {
			int x; scanf("%d", &x);
			l[x] ? l[x]-- : r[x]++; //抵消掉已经配对的情况
		}

		int res = 0; int left = 0, right = 0;
		rep(i, n) left += l[i], right += r[i]; //可以保证, l[i]和r[i]不同时存在

		int cha = abs(right - left); //左右袜子差值的数目, 一定是偶数
		rep(i, n) {
			int can = (left > right ? l[i] : r[i]) / 2; //判断下是哪种袜子多
			int pro = min(cha, can * 2); //提供的袜子数目
			res += pro / 2;
			cha -= pro;
		}

		res += min(left, right) + cha; //此时剩下的cha也一定是偶数, 我们会配对出cha / 2对, 花费为cha.
		printf("%d\n", res);
	}
	return 0;
}

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值