Educational Codeforces Round 72 (Rated for Div. 2) DE题解

昨晚差点被D卡死,然后E题题意一直没读对,导致线段树水题给漏了
D. Coloring Edges

题意:给你一个有向图,你要给每一条边涂色,问最少需要多少种颜色,使得如果存在环,那么环上的颜色不能全部相同。
解法:首先我们用拓扑排序判环,无环一种颜色够了,如果有环,其实最多两种颜色足够,因为一个有向边构成的环,肯定存在有向边 u -> v,u 大于 v,也肯定存在有向边 u -> v,u 小于 v,因此我们根据 u v 的大小关系去给每条边染色就好了。
#include<bits/stdc++.h>
#define pi pair<int, int>
#define mk make_pair
using namespace std;
const int maxn = 5000 + 10;
int d[maxn], n, ok = 1, vis[maxn];
vector<pi> G[maxn];
int check() {
    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (!d[i])
            q.push(i);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (auto v : G[u]) {
            vis[v.second] = 1;
            if (--d[v.first] == 0)
                q.push(v.first);
        }
    }
    for (int i = 1; i <= n; i++)
        if (d[i])
            return 0;
    return 1;
}
int main() {
    int m, u, v;
    cin>>n>>m;
    for (int i = 1; i <= m; i++) {
        cin>>u>>v;
        d[v]++;
        G[u].push_back(mk(v, i));
    }
    if (check()) {
        puts("1");
        for (int i = 1; i <= m; i++)
            printf("1 ");
        return 0;
    }
    puts("2");
    for (int i = 1; i <= n; i++)
    for (auto tmp : G[i]) {
        int id = tmp.second;
        int to = tmp.first;
        if (!vis[id]) {
            if (i < to)
                vis[id] = 1;
            else
                vis[id] = 2;
        }
    }
    for (int i = 1; i <= m; i++)
        printf("%d ", vis[i]);
}

E. Sum Queries?

题意:定义合法集合:设集合所有数的和为sum,那么sum十进制的每一位数,集合都存在一个数十进制下对应的数与其相等,求区间内非法集合的最小sum。
解法:我们发现,其实最少只要两个数就能构造非法集合,只要十进制下这两个数存在某位都不为0,比如310,20,十位上两个数都不为0,那么310,20构成的集合肯定非法,因此,我们用10个线段树分别维护十进制下每位数不为0的最小值次小值即可,比如1234,200,5,233,那么第1颗线段树维护的是个位上不为0的最小值次小值分别为5,233,第2颗线段树维护的是十位上不为0的最小值次小值分别为233,1234,第3颗线段树维护的是百位的200,233,后面亦同理。我们用线段树查每一位的最小值次小值,然后相加取min就是答案。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 10, inf = 2e9 + 1;
struct node {
    int mn[10], mn2[10];
    node operator+(const node& t) const {
        node tmp;
        for (int i = 0; i < 10; i++) {
            tmp.mn[i] = min(mn[i], t.mn[i]);
            if (mn[i] < t.mn[i])
                tmp.mn2[i] = min(t.mn[i], mn2[i]);
            else
                tmp.mn2[i] = min(mn[i], t.mn2[i]);
        }
        return tmp;
    }
} tree[maxn * 4];
#define ls o * 2
#define rs o * 2 + 1
#define m (l + r) / 2
void up(int o, int l, int r, int k, int v) {
    if (l == r) {
        for (int i = 0; i < 10; i++)
            tree[o].mn[i] = tree[o].mn2[i] = inf;
        for (int i = 0, x = v; i < 10; i++, x /= 10)
            if (x % 10)
                tree[o].mn[i] = v;
        return;
    }
    if (k <= m)
        up(ls, l, m, k, v);
    else
        up(rs, m + 1, r, k, v);
    tree[o] = tree[ls] + tree[rs];
}
node qu(int o, int l, int r, int ql, int qr) {
    if (l >= ql && r <= qr)
        return tree[o];
    if (qr <= m)
        return qu(ls, l, m, ql, qr);
    else if (ql > m)
        return qu(rs, m + 1, r, ql, qr);
    else
        return qu(ls, l, m, ql, qr) + qu(rs, m + 1, r, ql, qr);
}
int main() {
    int n, q, x, opt, l, r;
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);
        up(1, 1, n, i, x);
    }
    while (q--) {
        scanf("%d%d%d", &opt, &l, &r);
        if (opt == 1)
            up(1, 1, n, l, r);
        else {
            ll ans = inf;
            node tmp = qu(1, 1, n, l, r);
            for (int i = 0; i < 10; i++)
                ans = min(ans, 1ll * tmp.mn[i] + tmp.mn2[i]);
            if (ans >= inf)
                ans = -1;
            printf("%lld\n", ans);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 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
发出的红包

打赏作者

长沙橘子猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值