P3615 如厕计划

题意:2n个人排队上厕所,有两个厕所,一个男女都可以上,一个只有女的可以上,每个人上厕所都只有一分钟,你可以调整这些人的顺序,每个的怒气值为有多少后面的人排到自己前面了。求可以n分钟上完厕所的情况中,怒气最大的最小。

这题看半天没思路,只能看题解。
首先厕所一分钟都不能停,要么男女一起上两个厕所,要么女女一起,发现女生随意和谁匹配,考虑怎样满足男生的匹配。如果从前往后模拟看的话,我们遇到男生后面找不到女生的情况,就无从下手,因为前面的都已经匹配了。我们可以从后往前看,有一个规则就是男的不能比女的多两个以上,这个后缀开头一定是男生(如果不是往后找一定有),因为如果多一个,这个男生还可以和前面的女生匹配;但多了两个的话,如果和前面匹配掉一个,剩下还是多一个男生,但他已经不能和前面匹配了。如果和后面的匹配,就跟不行了,因为本来女生就少了。
所以记录后缀和,男生为1,女生为-1,如果当前位置后缀和为x,那么我们需要移走x - 1个男生,留下一个男生可以和前面匹配(如果有解一定可以匹配),那么有x-1个移到前面去了,就有人有x - 1的怒气值,所有情况求最大值即可(因为这样操作已经最优了,我们要求最大的最小,也就是每个后缀的最优解中最大的)。
还有一个问题是他的输入意思时一段复制多份然后连起来,因为数据太大我们无法还原字符串,但每个位置后面的后缀和还是可以算的,那么我们只要求这个段里最大后缀值就行了,如果这段的一份的值总和大于0,那么可以假设k-1份,剩下一份我们单独对这个一份字符串求个最大后缀,然后加起来,这就是这个段可以拼出的最大后缀。如果小于0,直接加上最大后缀就行了。

点击查看代码
void solve() {
	i64 n, m;
	std::cin >> n >> m;
	std::string s;
	std::vector<i64> sum(m), max(m), k(m);
	for (int i = 0; i < m; ++ i) {
		std::string t;
		std::cin >> t >> k[i];
		for (int j = (int)t.size() - 1; j >= 0; -- j) {
			sum[i] += t[j] == 'M' ? 1 : -1;
			max[i] = std::max(max[i], sum[i]);
		}
	}

	i64 tot = 0, ans = 0;
	for (int i = m - 1; i >= 0; -- i) {
		if (sum[i] > 0) {
			ans = std::max(ans, tot + (k[i] - 1) * sum[i] + max[i] - 1);
		} else {
			ans = std::max(ans, tot + max[i] - 1);
		}

		tot += sum[i] * k[i];
	}

	if (tot >= 2) {
		std::cout << -1 << "\n";
	} else {
		std::cout << ans << "\n";
	}
}
posted @   maburb  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示