没有时间参赛 直接补几道简单题吧~
B. Make Three Regions
题意:给一个2行的字符串,有block和其他东西,问把一个位置变成block让联通的部分变成3个部分,有多少种方法
思路:找规律,找所哟符合条件的块即可
void solve(){
int n;
cin >> n;
array<string, 2> s;
cin >> s[0] >> s[1];
int ans = 0;
for (int i = 1; i < n - 1; ++i) {
for (int j = 0; j < 2; ++j) {
if (s[j][i] == '.' && s[j][i - 1] == 'x' && s[j][i + 1] == 'x' &&
s[j ^ 1][i] == '.' && s[j ^ 1][i - 1] == '.' && s[j ^ 1][i + 1] == '.'
) {
ans ++;
}
}
}
cout << ans << '\n';
}
C. Even Positions
题意:给定长度为n的括号字符串,下标1~n,并且所有奇数位置上的字符让自己填。字符串的代价是匹配括号的距离。求所有填充字符的方法中最小的距离。
思路:一眼贪心,首先字符串要合法。在合法的前提下,肯定是如果有左括号就直接填右。如果没有左,就填左。
总结:这个算法的正确性证明比较有趣。 会不会出现按照这个策略填充,会出现到了最后左右括号数量不相等的情况?
void solve(){
int n;
cin >> n;
string s;
cin >> s;
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (s[i] == '_') {
if (!cnt) {
cnt ++;
s[i] = '(';
}
else {
s[i] = ')';
cnt --;
}
}
else {
cnt += (s[i] == '(' ? 1 : -1);
}
}
int ans = 0;
for (int i = 0; i < n; ++i) {
if (s[i] == '(') {
ans -= i;
}
else {
ans += i;
}
}
cout << ans << '\n';
}
D. Maximize the Root
题意:给定一颗树,每个结点有权值。每次操作可以将以当前结点v的子树中,所有的子节点权值-1,然后v的权值+1。不限操作次数的操作后,root根的编号为1的最大权值是多少?
思路:操作过程中要求结点权值不能为负数,所以结点1的权值增加的幅度,就是树中所有的结点,经过操作后值最小的最大值。于是问题转化为,经过若干次操作后,权值最小的结点,最大是多少。 直接dfs遍历,统计当前子树中权值最小的结点,分两种情况讨论。如果当前结点权值<最小权值结点,则当前结点权值变大,否则不变。
总结:一开始理解错题了,以为权值减小的结点只跟与当前结点直接相连的子节点有关。后来tc过不去才发现是子树中所有的结点都要操作,丢。
void solve(){
int n;
cin >> n;
vector<vector<int>> al(n + 1);
vector<long long> weights(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> weights[i];
}
for (int i = 2; i <= n; ++i) {
int p;
cin >> p;
al[p].push_back(i);
}
auto dfs = [&](auto&& self, int u)->long long {
long long x = INF_LL;
for (const auto& v : al[u]) {
x = min(self(self, v), x);
}
if (x!= INF_LL) {
if (u == 1) {
weights[u] += x;
}
else if (x > weights[u]) {
weights[u] = (weights[u] + x) / 2;
}
else {
weights[u] = x;
}
}
return weights[u];
};
cout << (dfs(dfs, 1)) << '\n';
}
有模板写程序就是好用
https://github.com/yxc-s/programming-template
标签:Educational,Rated,int,结点,Codeforces,++,weights,&&,权值 From: https://www.cnblogs.com/yxcblogs/p/18344682