Vp Codeforces Round 897 (Div. 2)

A题:green_gold_dog, array and permutation

题目大意:

给你一个大小为 n 的数组 a, 让你构造一个数组 b (b中的元素是(1, n)的排列), 对于i \epsilon (1, n),使得出现的 a_{i} - b_{i} 种类最多。

思路:

贪心。题目要求种类最多,那最多一定是 n 个。

我们固定 b 为 (1, 2, 3 ...), 发现如果 a 数组是降序的话,它们的差值a_{i} - b_{i}一定是单调递减的,这

样就使得种类一定为 n 个, 所以我们可以sort一遍 a, 然后按位置放 b。

// Problem: A. green_gold_dog, array and permutation
// Contest: Codeforces - Codeforces Round 897 (Div. 2)
// URL: https://codeforces.com/contest/1867/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int tt; cin >> tt;
	while (tt -- ) {
		int n; cin >> n;
		vector<PII> a(n);
		for (int i = 0; i < n; i ++ ) {
			int x; cin >> x;
			a[i] = {x, i};
		}
		sort(a.begin(), a.end(), [](PII aa, PII bb) {
			return aa.first > bb.first;
		});
		vector<int> res(n);
		for (int i = 0; i < n; i ++ ) {
			res[a[i].second] = i + 1;
		}
		for (auto x : res) cout << x << ' ';
		cout << endl;
	}
	return 0;
}

B题: XOR Palindromes

题目大意:

给你一个由01组成大小为 n 字符串 s,要求你输出一个大小为 n + 1的字符串,第 i 的位置上代表

着进行了 i 次异或操作(每位至多操作一次), 如果可以使得 s 变成回文串,那么该位上是1,

否则是0。 最后将你构造出的字符串输出。

思路:

我们先统计一下,一开始到底至少需要多少次才能使得 s 变成回文串,记这个次数为 cnt

在操作次数小于 cnt 的情况下, 一定是 0,无法将其变成回文串。

然后我们进行遍历, 将过程中s[i] = s[j]的部分,可以操作两次使得其还是个回文串。

但是我们值得注意的是, n 为奇数的情况下, 还可以多操作一次中间。

// Problem: B. XOR Palindromes
// Contest: Codeforces - Codeforces Round 897 (Div. 2)
// URL: https://codeforces.com/contest/1867/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int tt; cin >> tt;
	while (tt -- ) {
		int n; cin >> n;
		string s; cin >> s;
		s = " " + s;
		int cnt = 0;
		for (int i = 1; i <= n / 2; i ++ ) {
			if (s[i] != s[n - i + 1])
				cnt += 1;
		}
		vector<int> res(n + 2);
		res[cnt] = 1;
		if (n & 1) res[cnt + 1] = 1;
		for (int i = 1; i <= n / 2; i ++ ) {
			if (s[i] == s[n - i + 1]) {
				cnt += 2;
				res[cnt] = res[cnt + n % 2] = 1;
			}
		}
		for (int i = 0; i <= n; i ++ ) cout << res[i];
		cout << endl;
	}
	return 0;
}

C题: Salyg1n and the MEX Game

题目大意:

给定一个集合 S, 你为先手,每次可以往集合里加入一个数 x, 另一个人会每次删除一个数 y,

y小于x。定义你的得分为最后的Mex,请给出一个方案,使得这个方案得分大于等于两者都以

最优方式下棋的结果。

游戏以另一个人无法删除或者由你来结束(你是最后一步棋)

思路:

这个比 B 题简单多了啊,如果一开始你的得分是 3,集合为{0, 1, 2},那么你一开始可以往集合

里放入 3,使得你的得分变成了 4。后续你只需模仿另一个人的操作,他删什么,你就加什么。

这样就是两者都以最优方式下棋的结果。

证:一开始如果想让得分变大,你一定是往里面加入Mex。这样你的得分就会变成 >= Mex + 1 

另一个人删数只能删 <= Mex 的,记作 y,这样你的得分就会变成 y,为了保持你的最大得分

你不得不跟他进行同样的操作。

// Problem: C. Salyg1n and the MEX Game
// Contest: Codeforces - Codeforces Round 897 (Div. 2)
// URL: https://codeforces.com/contest/1867/problem/C
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int tt; cin >> tt;
	while (tt -- ) {
		int n; cin >> n;
		unordered_set<int> s;
		for (int i = 0; i < n; i ++ ) {
			int x; cin >> x;
			s.insert(x);
		}
		int i = 0;
		while (s.count(i)) i += 1;
		int y = 0;
		while (y >= 0) {
			cout << i << endl;
			cin >> y;
			i = y;
			if (y <= -1) break;
		}
	}
	return 0;
}

D题:Cyclic Operations 

放个代码,之后补思路qwq

跟后续补题一起传。

// Problem: D. Cyclic Operations
// Contest: Codeforces - Codeforces Round 897 (Div. 2)
// URL: https://codeforces.com/contest/1867/problem/D
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
#include <bits/stdc++.h>
#define endl '\n'
#define Yes cout << "YES" << endl
#define No cout << "NO" << endl
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int tt; cin >> tt;
	while (tt -- ) {
		int n, k; cin >> n >> k;
		vector<int> a(n + 1);
		for (int i = 1; i <= n; i ++ ) cin >> a[i];
		if (k == 1) {
			bool ok = true;
			for (int i = 1; i <= n; i ++ ) {
				if (a[i] != i) {
					ok = false;
				}
			}
			if (ok) Yes;
			else No;
		}else {
			bool ok = true;
			vector<int> vis(n + 1, false);
			for (int i = 1; i <= n; i ++ ) {
				if (vis[i]) continue;
				unordered_set<int> s;
				int now = i;
				while (!vis[now]) {
					s.insert(now);
					vis[now] = true;
					now = a[now];
				}
				if (s.count(now)) {
					int sz = 1;
					for (int j = a[now]; j != now; j = a[j], sz += 1);
					if (sz != k) {
						ok = false;
					}
				}
			}
			if (ok) Yes;
			else No;
		}
	}
	return 0;
}

 

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值