AcWing第7场周赛题解

A. 3758. 距离零点的时刻

题目链接:https://www.acwing.com/problem/content/3761/

题目大意:求 h 时 m 分过多少分钟到 0 分 0 秒。

解题思路:一条一共 \(24 \times 60 = 1440\) 分钟,所以答案为 (1440 - h* 60 - m) % 1440

示例程序:

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

int T, h, m;

int main() {
    cin >> T;
    while (T--) {
        cin >> h >> m;
        cout << (1440 - h* 60 - m) % 1440 << endl;
    }
    return 0;
}

B. 3759. 第k个字符串

题目链接:https://www.acwing.com/problem/content/3762/

题目大意:求由 \(n-2\)a\(2\)b 组成的字典序第 \(k\) 小的字符串。

解题思路:数学题,基于思想:把两个 b 放到较低的 \(m\) 个位置的方案数有 \(\frac{m(m-1)}{2}\) 种,所以可以二分找到第一个 b 的位置。第一个位置找到了,第二个就方便了。

示例程序:

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

int T, n;
long long k;

int get1st() {
    int l = 2, r = n, res;
    while (l <= r) {
        int mid = (l + r) / 2;
        long long tmp = (long long) mid * (mid - 1) / 2;
        if (tmp >= k) {
            res = mid;
            r = mid - 1;
        } else l = mid + 1;
    }
    return res;
}

void solve() {
    int p = get1st(), q = k - (long long) (p-1) * (p-2) / 2;
    for (int i = n; i >= 1; i--) {  // 从高到低枚举每一位
        if (i == p || i == q) putchar('b');
        else putchar('a');
    }
    puts("");
}

int main() {
    cin >> T;
    while (T--) {
        cin >> n >> k;
        solve();
    }
    return 0;
}

C. 3760. 最大剩余油量

题目链接:https://www.acwing.com/problem/content/3763/

题目大意:求书上从一点到另一点的且中途油都够的情况下的最多剩余油量。

解题思路:树形dp,状态见代码注释。需要搜两边,有点类似于树形dp求树的直径。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
int n, son[maxn];
long long ww[maxn], f[maxn][2], ans;
struct Edge { int v; long long w; };
vector<Edge> g[maxn];

// f[u][0] 表示 u 的所有子节点往上走到u的最大剩余油量
// f[u][1] 表示 u 的所有子节点往上走到u的第二大剩余油量
// son[u] 表示 f[u][0] 对应的那个子节点编号
void dfs1(int u, int p) {
    f[u][0] = f[u][1] = ww[u];
    for (auto e : g[u]) {
        int v = e.v;
        long long w = e.w;
        if (v != p) {
            dfs1(v, u);
            if (f[v][0] - w > 0) {
                long long tmp = f[v][0] - w + ww[u];
                if (tmp > f[u][0]) {
                    f[u][1] = f[u][0];
                    f[u][0] = tmp;
                    son[u] = v;
                }
                else if (tmp > f[u][1])
                    f[u][1] = tmp;
            }
        }
    }
}

// tmp表示节点 u 能够从它的父节点处获得的最大剩余油量
void dfs2(int u, int p, long long tmp) {
    assert(tmp >= 0);
    ans = max(ans, f[u][0]);
    ans = max(ans, tmp + ww[u]);
    for (auto e : g[u]) {
        int v = e.v;
        long long w = e.w;
        if (v != p) {
            long long t = max(0LL, tmp + ww[u] - w);
            if (v != son[u]) t = max(t, f[u][0] - w);
            else             t = max(t, f[u][1] - w);
            dfs2(v, u, t);
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> ww[i];
    for (int i = 1; i < n; i++) {
        int u, v; long long w;
        cin >> u >> v >> w;
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }
    dfs1(1, -1);
    dfs2(1, -1, 0);
    cout << ans << endl;
    return 0;
}
posted @ 2022-04-09 00:05  quanjun  阅读(41)  评论(0)    收藏  举报