Educational Codeforces Round 57 D. Easy Problem(DP?)

本文解析了Codeforces竞赛中一道有趣的D级题目,通过将问题转化为有序01背包问题,利用四个字符的特性,实现了线性的复杂度解决方法。文章详细介绍了如何遍历字符串并根据字符类型更新变量,最终输出最小成本。

题目:https://codeforces.com/contest/1096/problem/D

非常有意思的一题。

看起来像个背包,但是子序列这种东西,必须保证顺序,所以这其实是个有序的01背包。

有序的背包,只有4个字符,复杂度可以降到线性,扫一遍,仍然按每个字符“取或不取”来做即可。

#include <bits/stdc++.h>
using namespace std;

string s;
long long n, a, b, c, d;

int main() {
	cin >> n >> s;

	for(int i = 0; i < n; i++) {
		int h;
		cin >> h;
		if(s[i] == 'h') {
			a += h;
		} else if(s[i] == 'a') {
			b = min(a, b + h);
		} else if(s[i] == 'r') {
			c = min(b, c + h);
		} else if(s[i] == 'd') {
			d = min(c, d + h);
		}
	}
	cout << d;
	return 0;
}
### Codeforces Educational Round 168 Div. 2 Problem D 解析 #### 题目概述 题目描述涉及给定一个长度为 n 的数组 a 和整数 k,目标是在不超过 k 次操作的情况下使数组中的所有元素相等。每次操作可以选择任意数量的元素并将其增加或减少 1。 为了实现这一目标,需要找到一种策略来最小化所需的操作次数,使得最终所有的数组元素都相同[^1]。 #### 关键思路 核心在于理解到最优解通常是将所有元素变为中位数值。这是因为对于任何一组数字来说,调整至中位数所需的总移动量是最少的。具体而言: - 如果 n 是奇数,则存在唯一的中间值作为最佳目标; - 若 n 为偶数,则两个可能的目标分别是位于中心位置相邻的一对平均值之一; 考虑到最多可以执行 k 次修改动作,在某些情况下即使不是严格意义上的“中位数”,也可以通过适当选取接近它的其他值达到目的,只要满足条件即可。 #### 实现方法 以下是解决该问题的一种算法框架: ```cpp #include <bits/stdc++..h> using namespace std; int main() { int t; cin >> t; while (t--) { long long n, k; cin >> n >> k; vector<long long> a(n); for(auto &i : a) cin >> i; sort(a.begin(), a.end()); map<int,int> m; // 记录每个差异数出现频率 for(int i=0; i<n-1; ++i){ if(abs(a[i]-a[i+1])!=0)m[abs(a[i]-a[i+1])]++; } auto it=m.rbegin(); bool flag=true; while(k && !m.empty()){ if(it->second<=k){ k-=it->second; m.erase((++it).base()); }else{ cout << "NO\n"; flag=false;break; } it=m.rbegin(); } if(flag || m.size()==0)cout<<"YES\n"; } } ``` 此代码片段实现了上述逻辑的一部分,即尝试尽可能多地消除差异最大的一对元素之间的差距直到无法继续为止。需要注意的是这段代码并不完全适用于所有情况下的直接提交测试,而是提供了一个基本的方向指引。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值