返回顶部

Educational Codeforces Round 121 (Rated for Div. 2)题解

作者:@cherish.
课程学习内容为作者从学校的PPT处摘抄,仅供自己学习参考,若需转载请注明出处:https://www.cnblogs.com/cherish-/p/15813261.html


目前补到D

A. Equidistant Letters

题目描述:给你一个字符串s,该字符串只含有小写字母,且每个字母出现次数不超过2次,让你将s重排,使得每对出现次数为两次的字符的下标差相同。

思路:将s排序,使得每对出现次数为两次的字符的下标差都为1即可。

时间复杂度:O(Tnlogn)n为字符串长度。

参考代码:

string s;
void solve() {
	cin >> s;
	sort(s.begin(), s.end());
	cout << s << '\n';
	return;
}

B. Minor Reduction

题目描述:给你一个十进制数,长度为n,用字符串表示,你需要选择一个下标i,1i<n,然后将si,si+1的位置替换成si+si+1,问这样操作后能取得的最大值。

数据范围:1T104,2n10200000,n2×105

思路:先倒着扫一遍,若存在si+si+110就将该位置变成二者的和,否则将s1,s2合并。

时间复杂度:O(n)

参考代码:

string s;
void solve() {
	cin >> s;
	int n = static_cast<int>(s.size());
	for (int i = n - 2; i >= 0; --i) {
		int dx = s[i] - '0' + s[i + 1] - '0';
		if(dx >= 10) {
			s[i] = '1';
			s[i + 1] = '0' + (dx % 10);
			cout << s << '\n';
			return;
		}
	}
	int dx = s[0] - '0' + s[1] - '0';
	cout << dx << s.substr(2, n - 2) << '\n';
	return;
}

C. Monsters And Spells

题目描述:有n只怪物,出现在ki时刻拥有血条hi,假设不释放能量是释放了0的能量,那么每次你可以释放比前一次多一的能量,或者释放1点能量,只有当释放的能量不小于hi时才能杀死怪物,问将所有怪物杀死的最小能量释放数。

数据范围:1T104,1n100,1ki109,1hiki109,n104

思路:考虑倒着贪心,对于每一个出现在ki结点的怪物,他至少需要在kihi+1时刻开始从1开始递增。故倒着遍历,每次对于当前的i,找到一个j(j<i)使得kj<minp=j+1i{kphp+1}。记need表示杀死第i个怪物最小的开始时间,在上述找寻的过程中需要更新need,其中need=minp=j+1i{kphp+1}

时间复杂度:O(n)

参考代码:

void solve() {
	int n(0);
	cin >> n;
	vector<int>k(n + 1, 0), h(n + 1, 0);
	for (int i = 1; i <= n; ++i) cin >> k[i];
	for (int i = 1; i <= n; ++i) cin >> h[i];
	long long res = 0;
	int need = 0;
	int idx = n;
	while(idx){
		need = k[idx] - h[idx] + 1;
		long long dx = k[idx];
		--idx;
		while (idx && k[idx] >= need) {
			int dy = k[idx] - h[idx] + 1;
			need = min(need, dy);
			--idx;
		}
		dx = dx - need + 1;
		res += dx * (dx + 1) >> 1;
	}
	cout << res << '\n';
	return;
}

D. Martial Arts Tournament

题目描述:给你n个数字ai,让你求出两个整数x,y(x<y),将ai分成三部分,小于x,大于等于y和在[x,y)内的。为了让三部分中元素个数满足是二的幂次,你需要添加一些数字,求最少的添加数字的数量。

数据范围:1T104,1n2×105,1ain,n2×105

思路:考虑到ain,可以做一个前缀和优化计算区间内的数字个数,我们枚举x的位置,然后枚举二的幂次也即x+(1<<j)(0j20)作为y1,也即第二部分目标含有1 << j个元素,二分求y1在前缀和数组中的位置pos就可以求出三部分各含有多少元素。使用相应的幂次减去各部分含有的就是需要添加的,对所有情况取min即可。

时间复杂度:O(nlog2n)

参考代码:

const int N = 2e5 + 5;
vector<int> dis(N, 0);
void init() {
	int cur = 0;
	dis[0] = 1;
	for (int i = 1; i < N; ++i) {
		if (i > (1 << cur)) ++cur;
		dis[i] = 1 << cur;
	}
	return;
}
void solve() {
	int n(0), a(0);
	cin >> n;
	vector<int>pre(n + 1, 0);
	for (int i = 1; i <= n; ++i) cin >> a, pre[a]++;
	for (int i = 1; i <= n; ++i) pre[i] += pre[i - 1];
	int res = INT_MAX;
	for (int i = 0; i <= n; ++i) {
		if (i < n && pre[i] == pre[i + 1]) continue;
		int ans = dis[pre[i]] - pre[i];
		for (int j = 0; j <= 20; ++j) {
			int pos = upper_bound(pre.begin(), pre.end(), pre[i] + (1 << j)) - pre.begin() - 1;
			res = min(res, ans + (1 << j) + dis[pre[n] - pre[pos]] - (pre[n] - pre[i]));
			if (pos == n) break;
		}
	}
	cout << res << '\n';
	return;
}
posted @   cherish-lgb  阅读(187)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示