[POI2014]HOT-Hotels 加强版 解题报告

长链优化 DP 好题。
考虑朴素的 dp,可以先手模几组数据,发现满足要求的三元组类似下图:

因此,假设当前点为 u,当前处理的子节点为 v,与 u 点距离 j 的点有 fu,j 个,u 的子树中,满足 dis(lca(x,y),x)=dis(lca(x,y),y)=dis(lca(x,y),i)+j(x,y) 的点对数量。
可以得出如下转移:

g[u][j + 1] += f[v][j] * f[u][j + 1];
g[u][j - 1] += g[v][j];

f[u][j + 1] += f[v][j];

避免算重,答案应该在合并 uv 之前求出:

ans += f[u][j - 1] * g[v][j];
ans += f[v][j] * g[u][j + 1];

朴素转移时间、空间复杂度均为 O(n2)
n1e5 的范围下无法接受,考虑优化。
我们注意到转移只关心距离,而在树上,距离与深度相关,考虑用长链剖分与指针结合均摊复杂度。
注意到 fu,j+1gu,j1 的转移只和 fv,j,gv,j 有关,使用指针均摊这里的空间。
将整棵树长链剖分后,一条长链上的部分可以 O(len) 解决,其中 len 是长链长度。两条长链之间的合并由于已知深度,也可以 O(len) 解决,因此时间、空间复杂度均摊 O(n),可以通过本题。
代码只给出 dp 部分,f,g 为指针数组,dep_son 为长儿子,cur 为指针,fur 为从长链底到 u 的距离,可以发现,指针数组节约了大量的无效空间开销。

il void dfs2(int u, int fa) {
    // cerr << u << endl;
    if (dep_son[u]) 
        f[dep_son[u]] = f[u] + 1, g[dep_son[u]] = g[u] - 1, dfs2(dep_son[u], u);
    f[u][0] = 1; ans += g[u][0];
    for (int v : Es[u]) {
        if (v == fa || v == dep_son[u]) continue;

        f[v] = cur; cur += fur[v] << 1; g[v] = cur; cur += fur[v] << 1;
        dfs2(v, u);
        for (int i = 0; i < fur[v]; ++i) {
            if (i) ans += f[u][i - 1] * g[v][i];
            ans += g[u][i + 1] * f[v][i];
        }
        for (int i = 0; i < fur[v]; ++i) {
            g[u][i + 1] += f[u][i + 1] * f[v][i];
            if (i) g[u][i - 1] += g[v][i];
            f[u][i + 1] += f[v][i];
        }
    }
}
posted @   MisterRabbit  阅读(23)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示