Codeforces Round 972 (Div. 2)

A

如果有两个相同的字符,中间隔了若干个字符,形如 A******A,那么会产生很多回文子序列。

为了避免这种情况,考虑将相同字符放在相邻位置,于是得到本题的正解构造:

首先将长度尽可能平分到 5 组,每组用相同字符重复 n5 次或 n5 次。

#include <bits/stdc++.h>
using namespace std;
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;

#define IOS
#define MULTI

char mp[] = { 'a', 'e', 'i', 'o', 'u' };

void solve() {
	int n;
	cin >> n;
	int m = n % 5, t = n / 5;
	for (int i = 0; i < m; ++i)
		for (int j = 0; j <= t; ++j)
			cout << mp[i];
	for (int i = m; i < 5; ++i)
		for (int j = 0; j < t; ++j)
			cout << mp[i];
	cout << '\n';
}

int main() {
#ifdef IOS
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
#endif
#ifdef MULTI
	int TestCase = 1;
	for (cin >> TestCase; TestCase--;) solve();
#else
	solve();
#endif
	return 0;
}

B

  1. David 被两个老师夹住:
    那么答案非常显然,假设两个老师之间有 k 个空位,David 只能活 k2 轮。
    这个可以排序后用 lower_bound 找到 David 左右的老师。
  2. David 没有被老师夹住:
    那么 Daivd 显然会贪心地往边界跑,那么只需要求出离他最近的老师 x 的位置,答案就是 x1 或者 nx1
#include <bits/stdc++.h>
using namespace std;
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;

#define IOS
#define MULTI

void solve() {
	int n, m, q;
	cin >> n >> m >> q;
	vector<int> b(m);
	for (int &x : b)
		cin >> x;
	sort(begin(b), end(b));
	for (; q--;) {
		int x;
		cin >> x;
		if (x < b[0]) {
			cout << b[0] - 1 << '\n';
		} else if (x > b.back()) {
			cout << n - b.back() << '\n';
		} else {
			int p = upper_bound(begin(b), end(b), x) - begin(b);
			int y = b[p] - b[p - 1] - 1;
			cout << (y + 1) / 2 << '\n';
		}
	}
}

int main() {
#ifdef IOS
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
#endif
#ifdef MULTI
	int TestCase = 1;
	for (cin >> TestCase; TestCase--;) solve();
#else
	solve();
#endif
	return 0;
}

C

给人一种显然 dp 的感觉。用 dp[i][j] 表示前 i 个字符串种选了若干个字符串,选完后 Narek 贪心匹配到了第 j (0j<5) 个字符,此时的得分最大值。

那么只需要对每个字符串求出,假设之前已经匹配了 i (0i<5) 个字符,经过这个字符串后,贪心匹配到了哪个字符(j),完美匹配了几次(k)。用二元组 f(i)=(j,k) 记录即可转移。

#include <bits/stdc++.h>
using namespace std;
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;

#define IOS
#define MULTI

template<typename T>
void chmax(T &x, T y) {
	if (y > x)
		x = y;
}
int mp[256];

void solve() {
	int n, m;
	cin >> n >> m;
	vector<string> s(n);
	vector<int> cnt(n);
	vector<array<pair<int, int>, 5>> g(n);
	for (int i = 0; i < n; ++i) {
		cin >> s[i];
		array<pair<int, int>, 5> res;
		for (int j = 0; j < 5; ++j)
			res[j] = { 0, j };
		for (char ch : s[i]) {
			cnt[i] += !!mp[ch];
			for (int j = 0; j < 5; ++j) {
				auto &[ans, cur] = res[j];
				if (cur + 1 == mp[ch])
					++cur;
				if (cur == 5)
					cur = 0, ans += 5;
			}
		}
		g[i] = res;
		// cout << "string " << i << "\n";
		// for (int j = 0; j < 5; ++j) {
		// 	auto [a, c] = res[j];
		// 	cout << a << " " << c << '\n';
		// }
	}
	vector<array<int, 5>> f(n + 1);
	// f[i][j]: first i strings, matched to ch j, max
	for (int i = 0; i <= n; ++i)
		for (int j = 0; j < 5; ++j)
			f[i][j] = -1e9;
	f[0][0] = 0;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < 5; ++j) {
			// cout << "f[" << i << "][" << j << "] = " << f[i][j] << '\n';
			auto [ans, cur] = g[i][j];
			chmax(f[i + 1][cur], f[i][j] + 2 * ans - cnt[i]);
			chmax(f[i + 1][j], f[i][j]);
		}
	}
	int ans = 0;
	for (int i = 0; i < 5; ++i)
		chmax(ans, f[n][i]);
	cout << ans << '\n';
}

int main() {
	mp['n'] = 1;
	mp['a'] = 2;
	mp['r'] = 3;
	mp['e'] = 4;
	mp['k'] = 5;
#ifdef IOS
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
#endif
#ifdef MULTI
	int TestCase = 1;
	for (cin >> TestCase; TestCase--;) solve();
#else
	solve();
#endif
	return 0;
}

D

因为本题原做法的时间复杂度有问题,无法通过本题,暂时删去这部分内容。

E

没看。

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