惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
Google Developers Blog
S
SegmentFault 最新的问题
Microsoft Security Blog
Microsoft Security Blog
J
Java Code Geeks
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
量子位
P
Proofpoint News Feed
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
L
LangChain Blog
F
Fortinet All Blogs
C
Check Point Blog
博客园_首页
I
InfoQ
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
美团技术团队
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research

某岛

AtCoder Beginner Contest 409 Luogu P5325. 【模板】Min_25 筛 UOJ #188. 【UR #13】Sanrd AtCoder Beginner Contest 371 AtCoder Beginner Contest 369 RPGMaker 2k3 百科 OneShot 的考古 2024“开创拓芯”游戏创享节的相关记录 CJ 回来后的戒断反应 Luogu P10221. [省选联考 2024] 重塑时光 Luogu P5308 [COCI2018-2019#4] Akvizna wqs 二分 歌唱王国 Lean 相关 BZOJ 3153. Sone1 The 2023 ICPC World Finals Luxor 新巴别塔 Sora 的想象与思考 Facebook Hacker Cup 2023 Round 1 AtCoder Beginner Contest 322 LLaMA 2 相关 HuggingFace AI Game Jam ACL 2023 Trans 相关… Luogu P2053. [SCOI2007] 修车 Luogu P1973. [NOI2011] NOI 嘉年华 Luogu P1933. [NOI2010] 旅行路线 Luogu P1954. [NOI2010] 航空管制 Luogu P2048. [NOI2010] 超级钢琴 Luogu P2046. [NOI2010] 海拔
IZhO 2017. Problem F. Hard route
2023-06-03 · via 某岛

如果不考虑方案数的话是非常好写的,类似上一题,我们只需要维护向下的 top3 和向上的 top1 即可。
然后用均值不等式可以得到最优解一定是 a*(b+c) | a >= b >= c。

#include <lastweapon/io>
using namespace lastweapon;

const int N = int(1e5) + 9;

int dn[N][3], up[N];
VI adj[N]; int n;

void upd(int d[], int v) {
    if (v > d[0]) d[2] = d[1], d[1] = d[0], d[0] = v;
    else if (v > d[1]) d[2] = d[1], d[1] = v;
    else if (v > d[2]) d[2] = v;
}

void dfs1(int u = 1, int p = 0) {
    for (auto v: adj[u]) if (v != p) {
        dfs1(v, u);
        upd(dn[u], dn[v][0] + 1);
    }
}

void dfs2(int u = 1, int p = 0) {
    for (auto v: adj[u]) if (v != p) {
        checkMax(up[v], max(up[u], dn[u][0] != dn[v][0] + 1 ? dn[u][0] : dn[u][1]) + 1);
        dfs2(v, u);
    }
}

LL f(int x) {
    if (dn[x][1] == 0) return 0;
    if (up[x] > dn[x][0]) return (LL)up[x] * (dn[x][0] + dn[x][1]);
    if (up[x] > dn[x][2]) return (LL)dn[x][0] * (up[x] + dn[x][1]);
    if (dn[x][2] == 0) return 0;
    return (LL)dn[x][0] * (dn[x][1] + dn[x][2]);
}

int main() {

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("/Users/minakokojima/Documents/GitHub/ACM-Training/Workspace/out.txt", "w", stdout);
#endif

    DO(RD(n)-1) {
        int x, y; RD(x, y);
        adj[x].PB(y);
        adj[y].PB(x);
    }

    dfs1(); dfs2();

    LL z = 0; REP_1(i, n) checkMax(z, f(i));
    cout << z << endl;
}

考虑方案数的话,实现起来会麻烦很多。
主要上面的 a\b\c 里,a 是不参与计数的,只能各种讨论。

#include <lastweapon/io>
using namespace lastweapon;

const int N = int(5e5) + 9;

struct rec : public pair<LL, LL> {
    rec(LL a = 0, LL b = 0){
        fi = a, se = b;
    }
    rec& operator +=(const rec&r){
        if (fi == r.fi) se += r.se;
        else checkMax(*this, r);
        rTs;
    }
};

rec d[N], z = {0, 1};
VI adj[N]; int n;

void upd(rec d[], rec v) {
    if (v > d[0]) d[2] = d[1], d[1] = d[0], d[0] = v;
    else if (v > d[1]) d[2] = d[1], d[1] = v;
    else if (v > d[2]) d[2] = v;
}

void dfs1(int u = 1, int p = 0) {
    d[u] = {0, 1};
    for (auto v: adj[u]) if (v != p) {
        dfs1(v, u);
        d[u] += d[v];
    }
    d[u].fi += 1;
}

void dfs2(int u = 1, int p = 0, rec up = {0, 1}) {

    rec f[3] = {up};
    for (auto v: adj[u]) if (v != p) upd(f, d[v]);

    if (f[2].fi) {
        LL best = f[0].fi * (f[1].fi + f[2].fi);
        if (best >= z.fi) {
            LL ways, ways2 = up.fi == f[2].fi ? up.se : 0;
            for (auto v: adj[u]) if (v != p) if (d[v].fi == f[2].fi) ways2 += d[v].se;

            if (f[1].fi == f[2].fi) {
                ways = sqr(ways2);
                if (up.fi == f[2].fi) ways -= sqr(up.se);
                for (auto v: adj[u]) if (v != p) if (d[v].fi == f[2].fi) ways -= sqr(d[v].se);
                ways /= 2;
            } else {
                ways = ((f[0].fi == f[1].fi ? f[0].se : 0) + f[1].se) * ways2;
            }
            z += rec(best, ways);
        }
    }

    LL ways0 = 0, ways1 = 0;
    if (up.fi == f[0].fi) ways0 += up.se;
    else if (up.fi == f[1].fi) ways1 += up.se;
    for (auto v: adj[u]) if (v != p) {
        if (d[v].fi == f[0].fi) ways0 += d[v].se;
        else if (d[v].fi == f[1].fi) ways1 += d[v].se;
    }

    for (auto v: adj[u]) if (v != p) {
        LL a = f[0].fi+1, b = ways0;
        if (d[v].fi == f[0].fi) {
            if (d[v].se == ways0) a = f[1].fi+1, b = ways1;
            else b = ways0 - d[v].se;
        }
        dfs2(v, u, {a, b});
    }
}

int main() {

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("/Users/minakokojima/Documents/GitHub/ACM-Training/Workspace/out.txt", "w", stdout);
#endif

    DO(RD(n)-1) {
        int x, y; RD(x, y);
        adj[x].PB(y);
        adj[y].PB(x);
    }

    dfs1(); dfs2();
    cout << z.fi << " " << z.se << endl;
}

Posted by xiaodao
Category: 日常