【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(7)

比赛链接
本文发布于博客园,会跟随补题进度实时更新,若您在其他平台阅读到此文,请前往博客园获取更好的阅读体验。
跳转链接:https://www.cnblogs.com/TianTianChaoFangDe/p/18834991

开题 + 补题情况

这场就非常的难了,感觉有打区域赛的感觉了,开了两题,一个签到一个树形 DP,前面有个线段树的题写了个二分 + 线段树,不出意料地 TLE 了。
image

1008 - 木柜子组乐队

考虑用键盘手和不用键盘手,分别计算,很简单的组合数学。

点击查看代码
void solve()
{
    i64 a, b, c, d, e;std::cin >> a >> b >> c >> d >> e;

    i64 ans = 0;
    ans += a * b * c * d * e;
    ans += a * b * c * d * (d - 1) / 2;

    std::cout << ans>

1007 - 森林迷宫

一开始铸币了还在找两个点的 LCA 加换根。
这个题,只需要把起点或终点作为树的根,然后从深的那个点起,往上一层一层爬树,同时收集其他枝干的答案(只要往这个枝干走是正的,就说明对答案有贡献,走就一定是优的),每个枝干的答案只需要简单地进行树形 DP 就行,对于结点 \(i\) 的出了走过的那个结点之外的结点 \(j\)\(dp_i = \max(dp_i, dp_i + dp_j + p + q)\)
赛时代码写了依托答辩。

点击查看代码
#include 
#define inf32 1e9
#define inf64 2e18
#define ls o << 1 xss=removed xss=removed xss=removed xss=removed>> n;
    std::vector> e(n + 1);

    for(int i = 1;i < n>> u >> v >> p >> q;
        e[u].push_back({v, p, q});
        e[v].push_back({u, q, p});
    }

    std::vector> g(n + 1);
    std::vector fa(n + 1);
    std::vector dep(n + 1);
    int s, t;std::cin >> s >> t;

    auto dfs = [&](auto &&self, int st, int pre, i64 w) -> void {
        dep[st] = dep[pre] + 1;
        for(auto &i : e[st]) {
            if(i.v == pre)continue;
            g[st].push_back({i.v, i.p});
            fa[i.v] = {st, i.p, i.q};
            self(self, i.v, st, i.q);
        }
    };

    dfs(dfs, s, 0, 0);

    std::vector dp(n + 1);

    auto dfs1 = [&](auto &&self, int st) -> void {
        dp[st] = 0;
        for(auto &[v, w] : g[st]) {
            self(self, v);
            dp[st] = std::max(dp[st], dp[st] + dp[v] + fa[v].p + fa[v].q);
        }
    };

    dfs1(dfs1, s);


    auto lca = [&](int x, int y) -> int {
        while(x != y) {
            if(dep[x] < dep xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed> 0) {
                ans -= dp[pre] + fa[pre].p + fa[pre].q;
            }
        }
        ans += fa[s].q;
        pre = s;
        s = fa[s].v;
    }
    int pres = pre;

    pre = 0;
    while(t != lc) {
        ans += dp[t];
        if(pre != 0) {
            if(dp[pre] + fa[pre].p + fa[pre].q > 0) {
                ans -= dp[pre] + fa[pre].p + fa[pre].q;
            }
        }

        ans += fa[t].p;
        pre = t;
        t = fa[t].v;
    }
    int pret = pre;

    int hi = fa[lc].v;
    if(hi != 0) {
        i64 oh = dp[hi];
        if(dp[lc] + fa[lc].p + fa[lc].q > 0) {
            oh -= dp[lc] + fa[lc].p + fa[lc].q;
        }
        ans = std::max(ans, ans + oh + fa[lc].p + fa[lc].q);
    }

    i64 tmp = dp[lc];
    if(pres != 0) {
        if(dp[pres] + fa[pres].p + fa[pres].q > 0) {
            tmp -= dp[pres] + fa[pres].p + fa[pres].q;
        }
    }

    if(pret != 0) {
        if(dp[pret] + fa[pret].p + fa[pret].q > 0) {
            tmp -= dp[pret] + fa[pret].p + fa[pret].q;
        }
    }

    ans = std::max(ans, ans + tmp);

    std::cout << ans xss=removed>> t;
    while(t --)solve();

    return 0;
}


/*
What you want is what you love, so fight for it!
*/
From:https://www.cnblogs.com/TianTianChaoFangDe/p/18834991
天天超方的