Codeforces Round #635 (Div. 2)

比赛链接:https://codeforces.com/contest/1337

A. Ichihime and Triangle

题意

有正整数 $a,b,c,d$ ,选取 $a≤x≤b,b≤y≤c,c≤z≤d$,使得长为 $x,y,z$ 的三边能构成三角形。

思路

$x≤y≤z$,所以若想 $x+y>z$,$x$ 应尽可能大 ,$z$ 应尽可能小,即 $x=b$,$z=c$,所以 $b≤y≤c$,对该区间进行二分求 $y$ 的值即可,当然你也可以直接输出bcc。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int a, b, c, d; cin >> a >> b >> c >> d;
    int l = b, r = c;
    while (l + 1 < r) {
        int mid = (l + r) / 2;
        if (b + mid > c) {
            r = mid;
        } else {
            l = mid + 1;
        }
    }
    if (b + l > c) cout << b << ' ' << l << ' ' << c << "\n";
    else cout << b << ' ' << r << ' ' << c << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

B. Kana and Dragon Quest game

题意

可以进行 $n$ 次 $x=\lfloor\frac{x}{2}\rfloor+10$,$m$ 次 $x=x-10$ 的操作,$x$ 最终能否小于等于 $0$。

思路

$\lfloor\frac{x}{2}\rfloor+10≤x\ {\Rightarrow}\ x > 20$。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int x, n, m; cin >> x >> n >> m;
    while(x > 20 && n > 0) {
        x = x / 2 + 10;
        --n;
    }
    if (x <= 10 * m) cout << "YES" << "\n";
    else cout << "NO" << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

C. Linova and Kingdom

题意

从有 $n$ 个结点的树中选取 $k<n$ 个结点,求从 $k$ 个结点出发到结点 $1$ 路上所能访问到的未选取结点的个数之和的最大值(重复计数)。

思路

首先肯定是优先选取最深的叶子结点,其次就是权衡较深的父节点和较浅的叶子结点,如果我们要选取一个较深的父节点,那么它的更优的子结点一定已经被选过了,所以可以据此计算选取每个结点的收益,即 $depth - son\_num$,取前 $k$ 大即可。

代码

#include <bits/stdc++.h>
using namespace std;

const int M = 2e5 + 100;
vector<int> e[M], v;

int dfs(int u, int p, int dep) {
    int son = 1;
    for (int v : e[u]) {
        if (v != p) {
            son += dfs(v, u, dep + 1);
        }
    }
    v.push_back(dep - son + 1);
    return son;
}

int main() {
    int n, k; cin >> n >> k;
    for (int i = 0; i < n - 1; i++) {
        int u, v; cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs(1, 0, 0);
    sort(v.rbegin(), v.rend());
    cout << accumulate(v.begin(), v.begin() + k, 0LL);
}

D. Xenia and Colorful Gems

题意

从三个数组中各取一个数,使得三者不等且两两之差的平方和最小。

思路

三个数存在关系:$a<b<c$,只有枚举中间的 $b$ 才能保证求得的 $a,c$ 一定是最优的(反例见test1-case4)。

代码

#include <bits/stdc++.h>
#define resz resize
#define ub upper_bound
#define lb lower_bound
#define bg(x) x.begin()
#define ed(x) x.end()
#define all(x) x.begin(), x.end()
#define n_p next_permutation
#define LL long long
using namespace std;

inline LL cal(LL a, LL b, LL c) {
    return (a - b) * (a - b) + (b - c) * (b - c ) + (a - c) * (a - c);
}

void solve() {
    int sz[3]; for (int &i : sz) cin >> i;

    vector<int> v[3]; 
    for (int i = 0; i < 3; i++) {
        v[i].resz(sz[i]);
        for (int &j : v[i]) cin >> j;
        sort(all(v[i]));
    }

    LL ans = LLONG_MAX;
    int p[] = {0, 1, 2};
    do {
        for (int b : v[p[1]]) {
            auto a = ub(all(v[p[0]]), b);
            auto c = lb(all(v[p[2]]), b);

            if (a != bg(v[p[0]]) and c != ed(v[p[2]])) {
                --a;
                ans = min(ans, cal(*a, b, *c));
            }
        }
    } while(n_p(p, p + 3));
    cout << ans << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

 

上一篇:Educational Codeforces Round 87 (Rated for Div. 2)


下一篇:HDU - 2199 - Can you solve this equation?(二分)