Educational Codeforces Round 110 C(最长连续字串,dp),D(左右子树继承贡献dp)

C. Unstable String


题目大意:

给定一个长度为n的字符串且只包括'0','1','?',其中如果一个字串是由01交替组成的则称谓不稳定的,如果碰到'?'则可以将其转化为0/1,求不稳定的字串的个数。(单独的0/1/?也为不稳定字串)。


解题思路:

不稳定字串的个数可以转化为到第i位,不稳定字串的最大长度

例如01010,对于第1位,贡献为1,第2位贡献为2(1,01),第三位贡献为3(0,10,010),以此类推
所以定义f[i][j]为,第i位为0/1时的最长不稳定串的长度,每次ans += max(f[i][0],f[i][1])

代码实现:

#include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 2e5 + 10, inf = 1e18;


void solve() {
	string s;
	cin >> s;
	int n = s.size();
	vector<vector<int>> f(n, vector<int>(2, 0));
	int ans = 0;
	for (int i = 0; i < n; ++i) {
		if (i == 0) {
			if (s[i] == '0') f[i][0] = 1;
			else if (s[i] == '1') f[i][1] = 1;
			else f[i][0] = f[i][1] = 1;
		} else {
			if (s[i] == '0') f[i][0]  = f[i - 1][1] + 1;
			else if (s[i] == '1') f[i][1] = f[i - 1][0] + 1;
			else {
				f[i][1] = f[i - 1][0] + 1;
				f[i][0] = f[i - 1][1] + 1;
			}
		}
		ans += max(f[i][0],f[i][1]);
	}
	cout<<ans<<endl;


}
int tt;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	tt = 1;
	cin >> tt;
	while (tt--) solve();


	return 0;
}

D. Playoff Tournament

题目大意:

给定一个数n,总共有1<<n个人参加比赛,其中1与2对抗,3与4对抗...,每轮胜出的人都会和相邻比赛胜出的人继续比赛,直到最后胜出一人。
现在给定一个长度为(1<<n-1)的字符串只包含0/1/?用来表示第i场比赛的获胜规则
,0表示id较低者获胜,1表示id较高者获胜,?表示都有可能胜。
给定m次修改,求每次修改后可能胜出的人数。


解题思路:

对于每场比赛如果规定了比赛规则那么毫无疑问,每场的能够决定的胜者个数则为1,下一轮比赛则如果为0,胜者个数则会继承于左子树,否则继承于右子树,如果是?则继承左右子树之和。其实这样一分析dp的过程就就浮现出来了,定义f[i]表示第i场可能胜出的人数,如果第i场为0,则继承f[i*2],否则继承f[i*2+1],如果为?则继承f[i*2]+f[ i*2+1] (数组模拟二叉树)

代码实现:

#include<bits/stdc++.h>
using namespace std;
# define int long long
# define endl "\n"
const int N = 2e5 + 10, inf = 1e18;

void solve() {
	int n;
	cin >> n;
	string s;
	cin >> s;
	int len = 1 << n;
	vector<int> f(2 * len);
	for (int i = len; i <= len * 2 - 1; ++i) {
		f[i] = 1;
	}
	int now = 0;
	for (int i = len - 1; i >= 1; --i) {
		f[i] = (s[len - 1 - i] == '0' ? f[2 * i+1] : (s[len - 1 - i] == '1' ? f[2 * i] : f[2 * i] + f[2 * i + 1]));
	}
	int q;
	cin >> q;
	while (q--) {
		int p;
		char c;
		cin >> p >> c;
		--p;
		s[p] = c;
		for (int i = len - 1 - p; i != 0; i /= 2) {
			f[i] = (s[len - 1 - i] == '0' ? f[2 * i+1] : (s[len - 1 - i] == '1' ? f[2 * i] : f[2 * i] + f[2 * i + 1]));
		}
		cout<<f[1]<<endl;
	}

}
int tt;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	tt = 1;
//	cin >> tt;
	while (tt--) solve();


	return 0;
}
posted @ 2023-01-14 00:08  empty_y  阅读(33)  评论(0)    收藏  举报