CodeForces 2033G Sakurako and Chefir 题解

news/2024/10/25 8:21:32/文章来源:https://www.cnblogs.com/bluewindde/p/18501690

题意:给定一棵树,多次询问在以节点 \(v\)\(k\) 级祖先为根的子树内,从点 \(v\) 出发的最长简单路径。

显然可以将所求路径分为终点在 \(v\) 的子树内和终点在 \(v\) 的子树外,前者容易处理。

考虑其他节点贡献的路径,容易想到枚举 \(v\) 每个合法祖先 \(u\) 作为 LCA,查询 \(v\) 所在的子树与 \(u\) 的其他子树之间的贡献。贡献可以使用主席树处理。具体而言,由树上路径计算方式 \(d = dis_u + dis_v - 2 \cdot dis_{lca}\),设 \(rt_u\) 表示记录节点 \(u\) 的子树内所有点的深度的主席树,查询时减去 \(v\) 所在子树的所有点的深度,并查询最大深度。

于是得到一个 \(O(qn \log n)\) 的做法,考虑优化。

发现每次查询时跳了很多祖先,而对于一个确定的祖先与其确定的子树,没有必要查询多次。使用树上启发式合并:预处理重儿子的答案作为该节点的权值,树剖查询链最大值,跳轻链时再使用前述方法。优化至 \(O(q \log^2 n)\),可以通过。

#include <algorithm>
#include <iostream>
#include <vector>using namespace std;const int inf = 1e9;int lg[200005];int n, q;
vector<int> vec[200005];int rt[200005];
struct node {int ls, rs, val;
} d[16000005];
int cnt;
static inline int clone(int p) {d[++cnt] = d[p];return cnt;
}
static inline int insert(int x, int s, int t, int c, int p) {p = clone(p);if (s == t) {d[p].val += c;return p;}int mid = (s + t) >> 1;if (x <= mid)d[p].ls = insert(x, s, mid, c, d[p].ls);elsed[p].rs = insert(x, mid + 1, t, c, d[p].rs);d[p].val = d[d[p].ls].val + d[d[p].rs].val;return p;
}
static inline int merge(int s, int t, int u, int v) {if (!u || !v)return clone(u | v);int p = ++cnt;if (s == t) {d[p].val = d[u].val + d[v].val;return p;}int mid = (s + t) >> 1;d[p].ls = merge(s, mid, d[u].ls, d[v].ls);d[p].rs = merge(mid + 1, t, d[u].rs, d[v].rs);d[p].val = d[d[p].ls].val + d[d[p].rs].val;return p;
}
static inline int query(int s, int t, int u, int v) {if (s == t)return d[v].val - d[u].val > 0 ? s : -inf;int mid = (s + t) >> 1;if (d[d[v].rs].val - d[d[u].rs].val > 0)return query(mid + 1, t, d[u].rs, d[v].rs);return query(s, mid, d[u].ls, d[v].ls);
}int dep[200005];
int st[200005][20];
int siz[200005];
int son[200005];
int top[200005];
int dfn[200005], dfn_clock;
int nfd[200005];
int pre[200005][20];
static inline void dfs(int u, int fa) {dep[u] = dep[fa] + 1;st[u][0] = fa;for (int i = 1; i <= 18; ++i)st[u][i] = st[st[u][i - 1]][i - 1];siz[u] = 1;rt[u] = insert(dep[u], 1, n, 1, rt[u]);for (auto v : vec[u]) {if (v == fa)continue;dfs(v, u);siz[u] += siz[v];if (siz[v] > siz[son[u]])son[u] = v;rt[u] = merge(1, n, rt[u], rt[v]);}
}
static inline void dfs2(int u) {nfd[dfn[u] = ++dfn_clock] = u;if (!son[u]) {pre[dfn[u]][0] = -inf;return;}top[son[u]] = top[u];dfs2(son[u]);pre[dfn[u]][0] = query(1, n, rt[son[u]], rt[u]) - 2 * dep[u];for (auto v : vec[u]) {if (v == st[u][0] || v == son[u])continue;top[v] = v;dfs2(v);}
}
static inline int jump(int x, int k) {for (int i = 0; i <= 18; ++i)if ((k >> i) & 1)x = st[x][i];return x;
}
static inline int LCA(int u, int v) {if (dep[u] < dep[v])swap(u, v);u = jump(u, dep[u] - dep[v]);if (u == v)return u;for (int i = 18; i >= 0; --i)if (st[u][i] != st[v][i]) {u = st[u][i];v = st[v][i];}return st[u][0];
}static inline void build() {for (int i = 2; i <= n; ++i)lg[i] = lg[i >> 1] + 1;for (int j = 1; j <= 18; ++j)for (int i = 1; i + (1 << j) - 1 <= n; ++i)pre[i][j] = max(pre[i][j - 1], pre[i + (1 << (j - 1))][j - 1]);
}
static inline int query(int l, int r) {int len = lg[r - l + 1];return max(pre[l][len], pre[r - (1 << len) + 1][len]);
}static inline void solve() {cin >> n;for (int i = 1; i <= cnt; ++i)d[i] = {0, 0, 0};cnt = dfn_clock = 0;for (int i = 1; i <= n; ++i) {vec[i].clear();rt[i] = son[i] = top[i] = 0;for (int j = 0; j <= 18; ++j)st[i][j] = pre[i][j] = 0;}for (int i = 1; i < n; ++i) {int u, v;cin >> u >> v;vec[u].push_back(v);vec[v].push_back(u);}dfs(1, 0);top[1] = 1;dfs2(1);build();cin >> q;while (q--) {int x, k;cin >> x >> k;int u = st[x][0];int v = max(jump(x, k), 1);int ans = min(k, dep[u]);while (u && dep[u] > dep[v] && top[u] != top[v]) { // DSU on treeint w = query(1, n, rt[jump(x, dep[x] - dep[u] - 1)], rt[u]);ans = max(ans, dep[x] + w - 2 * dep[u]);if (dfn[top[u]] < dep[u])ans = max(ans, dep[x] + query(dfn[top[u]], dfn[u] - 1));u = st[top[u]][0];}if (dep[u] >= dep[v]) {int w = query(1, n, rt[jump(x, dep[x] - dep[u] - 1)], rt[u]);ans = max(ans, dep[x] + w - 2 * dep[u]);if (dfn[v] < dfn[u])ans = max(ans, dep[x] + query(dfn[v], dfn[u] - 1));}// 这是暴力的实现方式// int ans = 0;// int u = st[x][0];// --k;// while (u && k >= 0) {//     int w = query(1, n, rt[jump(x, dep[x] - dep[u] - 1)], rt[u]);//     ans = max(ans, dep[x] + w - 2 * dep[u]);//     u = st[u][0];//     --k;// }ans = max(ans, query(1, n, 0, rt[x]) - dep[x]);cout << ans << ' ';}cout << endl;
}signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);solve();cout.flush();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/821541.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware vSphere 8.0 Update 3d 下载 - 企业级工作负载平台

VMware vSphere 8.0 Update 3d 下载 - 企业级工作负载平台VMware vSphere 8.0 Update 3d 下载 - 企业级工作负载平台 vSphere 8.0U3 | ESXi 8.0U3 & vCenter Server 8.0U3 请访问原文链接:https://sysin.org/blog/vmware-vsphere-8-u3/ 查看最新版。原创作品,转载请保留出…

10.21 ~ 10.27

CSP10.21 Day -4 快 CSP 啦…… 话说真的应该这么早就开始记“Day x”吗 为啥这几天这么冷啊要冻死了 😥 上午模拟赛。 开题。看 T1,发现自己又不会 T1。 不行今天一定要签上! 然后磕了一个小时 T1,还是不会。 算了一下发现暴力是 \(O(n!)\),\(n\) 最大可达 \(15\),直接…

干货分享:Air700ECQ的硬件设计,第三部分

​ 5. 电器特性,可靠性,射频特性 5.1. 绝对最大值 下表所示是模块数字、模拟管脚的电源供电电压电流最大耐受值。 表格 17:绝对最大值参数最小最大单位VBAT-0.34.7VVBUS-0.35.5V电源供电峰值电流01.5A电源供电平均电流(TDMA一帧时间)00.7A数字管脚处电压-0.33.6V模拟管脚…

干货分享:Air700ECQ的硬件设计,第二部分

​ 接下来分享第二部分。 3.10. 功能管脚 3.10.1. MAIN_RI管脚名类型序号电压域作用MAIN_RIDO5LDOAON振铃信号,唤醒输出管脚,用于唤醒AP表格 10:MAIN_RI 信号动作状态MAIN_RI 应答待机高电平语音呼叫变为低电平,之后:通话建立时变为高电平 使用AT命令ATH挂断语音,MAIN_R…

干货分享:Air700ECQ的硬件设计,第一部分

​一、绪论 Air700ECQ是一款基于移芯EC716E平台设计的LTE Cat 1无线通信模组。支持移动双模FDD-LTE/TDD-LTE的4G远距离无线传输技术。以极小封装,极高性价比,满足IoT行业的数传应用需求。例如共享应用场景,定位器场景,DTU数传场景等。 ​ 图表 1:功能框图 二、综述 表格 1…

美团商家联系方式批量采集软件地图卖家电话提取器

美团商家联系方式批量采集软件地图卖家电话提取器作者V♥553813195欢迎交流 关于美团商家联系方式批量采集软件及地图卖家电话提取器,这类软件通常旨在帮助用户快速、批量地获取美团平台上商家的联系方式,包括但不限于电话号码。以下是对这类软件的详细介绍:一、软件功能 批…

抖音抖店商家联系方式批量提取软件快手卖家联系方式批量采集器

作者V♥553813195抖音抖店商家联系方式批量提取软件快手卖家联系方式批量采集器 由于直接获取抖音精选联盟商家信息的代码涉及到访问抖音的API,而这些API通常是私有的、受保护的,并且需要特定的授权和认证才能访问,因此我无法直接提供一个能够直接获取这些信息的代码示例。 …

读数据工程之道:设计和构建健壮的数据系统19数据存储系统 (下)

数据存储系统(下)1. 对象存储 1.1. 对象存储包含各种形状和大小的对象1.1.1. Amazon S3、Azure Blob Storage和Google Cloud Storage(GCS)是广泛使用的对象存储1.1.2. 许多云数据仓库(以及越来越多的数据库)利用对象存储作为其存储层,而云数据湖通常位于对象存储上1.1.3. 对…

关于 服务器的 http server 架设与配置 梳理

目标:想将自己的一些文件放到服务器上,然后谁都能下载,由于不懂这方面,所以跟着网上教程走,但是还是踩了好多坑.这里再梳理一下.首先肯定是要有个自己的云服务器. 然后开始搭建 web服务器.这里我是跟着一个教程走的,用的是 nginx. 链接:Http服务器搭建-CSDN博客怕博主删了,这里…

Codeforces Round 981 div3 个人题解(A~G)

Codeforces Round 981 div3 个人题解(A~G) Dashboard - Codeforces Round 981 (Div. 3) - Codeforces 火车头 #define _CRT_SECURE_NO_WARNINGS 1#include <algorithm> #include <array> #include <bitset> #include <cmath> #include <cstdio> …

JetBrains终于正式宣布:WebStorm免费开放个人开发者使用了!

10 月 24 日,正值程序员节之际,JetBrains 正式宣布:WebStorm 个人版现已全面免费开放使用。众所周知,WebStorm 是一个非常好用的 IDE,但是不免费。为响应开发者社区的需求,JetBrains 决定,针对非商业用途,WebStorm 个人版将不再收取费用,真正实现了对个人开发者的免费…

ubuntu22.04桌面版开启root用户登陆并开启root用户远程ssh连接

ubuntu22.04桌面版开启root用户登陆并开启root用户远程ssh连接最近在使用Ubuntu22.04时需要用到root用户登录桌面,于是配置了下系统,也在网上查找了类似的文章,发现几篇文章都操作都存在一定的问题,所以在这里写了一份较为完整的,这份文档是清澈过可以正常使用运行的,具体…