Educational Codeforces Round 168 (Rated for Div. 2)部分题解A~D

A. Strong Password

题目大意

给定一个字符串,字符串的输入时间为:

  • 第一个字符输入需2秒;

  • 若该字符与上一个输入字符一致,则输入需1秒,否则为2秒

问在字符串中任意插入一个字符后,输入最长时间。

思路

考虑,当破坏字符串连续字符输入可以有效提高时间;如果存在相同连续字符,则插入不同字符破坏,否则在末尾插入与末尾不相同的即可。

代码实现
void solve() {
    string s; cin >> s;
    int id = -1;
    for (int i = 0; i < s.size() - 1; i++) {
        if (s[i] == s[i + 1])id = i;
    }
    for (int i = 0; i < s.size(); i++) {
        cout << s[i];
        if (i == id) {
            if (s[i] == 'a') {
                cout << "b";
            }
            else {
                cout << "a";
            }
        }
    }
    if(id==-1){
        if (s.back() == 'a') {
            cout << "b";
        }
        else {
            cout << "a";
        }
    }
    cout << "\n";
}

B. Make Three Regions

题目大意

给定一个两行n列的网格,网格中存在一些墙,保证网格中只存在一个连通区域。

问有多少个可以修改的位置,使得连通块变为三个。

思路

只有两种情况,看代码判断处吧。

代码实现
char dt[4][210000];
void solve() {
    ll n; cin >> n;
    dt[1][0] = dt[2][0] = dt[1][n + 1] = dt[2][n + 1] = 'x';
    for (int i = 1; i <= 2; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> dt[i][j];
        }
    }
    ll ans = 0;
    for (int i = 1; i <= 2; i++) {
        for (int j = 1; j <= n; j++) {
            if (dt[i][j] == '.') {
                if (i == 1) {
                    if (dt[2][j] == '.' && dt[2][j - 1] == 'x' && dt[2][j + 1] == 'x' && dt[1][j - 1] == '.' && dt[1][j + 1] == '.') {
                        ans++;
                    }
                }
                else {
                    if (dt[1][j] == '.' && dt[1][j - 1] == 'x' && dt[1][j + 1] == 'x' && dt[2][j - 1] == '.' && dt[2][j + 1] == '.') {
                        ans++;
                    }
                }
            }
        }
    }
    cout << ans << "\n";
}

C. Even Positions

题目大意

给定一奇数位之上全部消失的括号序列,问如何补充括号序列,使代价最小。

代价计算为,待补充的位置与之匹配位置的长度。

思路

对于括号来说,越近补充越好。

我们从前往后扫一次左括号,从后往前扫一次右括号,计算即可。

代码实现
void solve() {
    ll n; cin >> n;
    string s; cin >> s;
    ll ans = 0;
    queue<ll>id;
    vector<bool>v(s.size(),false);
    for (int i = 0; i < s.size(); i++) {
        if (s[i] == '(') {
            id.push(i);
        }
        if (s[i] == '_') {
            if (id.size()) {
                ll now = id.front(); id.pop();
                ans += i - now;
                v[i] = true;
                v[now] = true;
                s[i] = 'x';
            }
        }
    }
    while (id.size())id.pop();
    for (int i = s.size(); i >= 0; i--) {
        if (s[i] == ')') {
            id.push(i);
        }
        if (s[i] == '(' && v[i] == false&&id.size()) {
            id.pop();
        }
        if (s[i] == '_'&&v[i]==false) {
            if (id.size()) {
                ll now = id.front(); id.pop();
                ans += now - i;
                s[i] = 'x';
            }
        }
    }
    cout << ans << "\n";
}

D. Maximize the Root

题目大意

给定一棵有根树,根节点为1,每个结点均有权值。现在有以下操作,当我们选择一结点加1时,我们要求他的子树上的所有结点均减1。在保证最后树上无负值的情况下,问根节点1的权值最大值为多少。

思路

考虑,对于每个结点来说,如果他比他子结点权值最小值都要大,那么他的最大值为应该为他子树上的最小值与他本身全值得一半;如果他得值要比他的子节点权值最小值还要小,那么不需要不变化。

拓扑排序,从叶节点一直按上述操作推上来,每次当结点弹出得时候,对结点的子节点按权值排序,然后比较最小值更新当前点权值即可。当操作到根节点1的时候,直接将根节点的子节点权值的最小值加上即是可以得到的最大值。

代码实现
ll fa[210000];
ll val[210000];
ll in[210000];
vector<ll>to[210000];
void solve() {
    ll n; cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> val[i];
        in[i] = 0;
        to[i].clear();
    }
    for (int i = 2; i <= n; i++) {
        ll F; cin >> F;fa[i] = F;
        to[F].push_back(i);
        in[i]++;
        in[F]++;
    }
    queue<ll>id;
    for (int i = 2; i <= n; i++) {
        if (in[i] == 1) {
            id.push(i);
            in[i]--;
        }
    }
    while (id.size()) {
        ll now = id.front(); id.pop();
        if (to[now].size()) {
            sort(to[now].begin(), to[now].end(), [&](auto a, auto b) {
                return val[a] < val[b];
                });
            ll y = to[now][0];
            if (now == 1) {
                val[1] += val[y];
                break;
            }
            if (val[y] < val[now]) {
                val[now] = val[y];
            }
            else {
                val[now] = (val[y] + val[now]) / 2;
            }
        }
        ll x = fa[now];
        in[x]--;
        if (x == 1) {
            if (in[x] == 0) {
                id.push(x);
            }
        }
        else {
            if (in[x] == 1) {
                id.push(x);
            }
        }
    }
    cout << val[1] << "\n";
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值