Educational Codeforces Round 123 (Rated for Div. 2)

Educational Codeforces Round 123 (Rated for Div. 2)

A Doors and Keys

Solution:

模拟

void solve(){
	string s;
	cin >> s;
	s = " " + s;
	int r, g , b;
	r = g = b = 0;
	for (int i = 1;i <= 6;i ++) {
		if(s[i] == 'r') r = 1;
		if(s[i] == 'g') g = 1;
		if(s[i] == 'b') b = 1;
		if(s[i] == 'R' && !r) {
			cout << "NO" << endl;
			return;
		}
		if(s[i] == 'G' && !g) {
			cout << "NO" << endl;
			return;
		}
		if(s[i] == 'B' && !b) {
			cout << "NO" << endl;
			return;
		}
	}
	cout << "YES" << endl;
}

B Anti-Fibonacci Permutation

Solution:

考虑逆序排列一定符合要求,每次交换最后一个元素和倒数第二个元素即可

void solve(){
	int n;
	cin >> n;
	vector<int> a(n + 1);
	for (int i = 1;i <= n;i ++) a[i] = n - i + 1;
	int last = n;
	for (int i = 1;i <= n;i ++) {
		for (int j = 1;j <= n;j ++) {
			cout << a[j] << ' ';
		}
		cout << endl;
		swap(a[last],a[last - 1]);
		last --;
	}
}

C

Solution:

本题\(x > 0\)所以考虑给每个可能的最大的子段加上$k * x $即可。

求最大子段的过程用DP实现,定义\(f_{i}\)为长度为\(i\)时的最大字段和。

void solve(){
	int n, x;
	cin >> n >> x;
	vector<int> a(n + 1);
	vector<int> s(n + 2);
	for (int i = 1;i <= n;i ++) cin >> a[i];
	for (int i = 1;i <= n;i ++) {
		s[i] = s[i - 1] + a[i];
	}
	vector<int> f(n + 1,-1e15);
	f[0] = 0;
	for (int i = 1;i <= n;i ++) {
		for (int j = i;j <= n;j ++) {
			f[i] = max(f[i], s[j] - s[j - i]);
		}
	}
	// for (int i = 1;i <= n;i ++) {cout << f[i] << ' ';} cout << endl;
	for (int k = 0;k <= n;k ++) {
		int mx = -1e9;
		for (int i = 1;i <= n;i ++) {
			mx = max(mx, f[i] + min(k , i) * x);
		}
		cout << max(mx, ll(0)) << ' ';
	}
	cout << endl;
}

D

Solution:

呜呜呜自己确实没想到这么做,正难则反,正着考虑会发现状态很多且很难找到符合复杂度的递推关系,所以我们反着考虑,因为最后一次染色肯定会覆盖之前的染色,我们只需要考虑,到最后一次染色之前,出现了多少个可以更新的状态即可。

void solve(){
	int n , m, k , q;
	cin >> n >> m >> k >> q;
	int ans = 1;
	vector<bool> fn(n + 1);
	vector<bool> fm(m + 1);
	vector<PII> cnt(q + 1);
	for (int i = 1;i <= q;i ++) {
		cin >> cnt[i].first >> cnt[i].second;
	}
	int nowx = 0;
	int nowy = 0;
	for (int i = q;i >= 1;i --) {
		if(nowx == n || nowy == m) continue;
		int x, y;
		x = cnt[i].first, y = cnt[i].second;
		int t = 1;
		if(fn[x] == 0)
		fn[x] = 1, nowx++,t = k;
		if(fm[y] == 0) 
		fm[y] = 1, nowy++,t = k;
		ans = ans * t % mod;
	}
	cout << ans << endl;

E

Solution:

这题怎么说呢,感觉在纸上画画就会比较清楚了。

我的思路是这样的,先想到最后一个点右下的所有点,都是可以走到的点,必然被加入到答案里去,再考虑前面的点,第一个转角之前是无法改变状态的,但是在转角之后,每一个前进的方向都可以往他的相反方向加入一个\(n - cnt_{R}\)或者\(n - cnt_{D}\),所以就有式子了,转角前的点答案全算上去,因为算最后右下覆盖的点的时候,多算了一个最终的点,前面减一就可以了。

void solve(){
	int n;
	string s;
	cin >> n >> s;
	int len = s.length();
	s = " " + s;
	int fx = 1;
	int fy = 1;
	for (int i = 1;i <= len;i ++) {
		if(s[i] == 'R') fx ++;
		else fy ++;
	}
	int ans = 1;
	if(fx == 1 || fy == 1) {
		cout << n << endl;
		return ;
	}
	int l = 2;
	while(s[l] == s[l - 1])l ++;
	ans += l - 2;
	for (int i = l;i <= len;i ++) {
		if(s[i] == 'R') ans += (n - fy);
		else ans += (n - fx);
		ans ++;
	}
	ans += (n - fx + 1) * (n - fy + 1);
	cout << ans << endl;
}
posted @ 2023-03-14 20:07  zwhqwq  阅读(18)  评论(0编辑  收藏  举报