首页 > 其他分享 >题解 ABC267F【Exactly K Steps】

题解 ABC267F【Exactly K Steps】

时间:2023-10-16 22:44:36浏览次数:29  
标签:intoxicated int 题解 scanf Exactly 祖先 Steps include 最远

(accoders::NOI #5541. 醉(intoxicated))

题目描述

Robin 有一棵树,他有 \(m\) 次询问,每次询问他给你 \(u,k\),你需要输出树上的一个节点 \(v\) 满足 \(dist(u,v)=k\),或者报告无解。

\(dist(u,v)\) 表示树上 \(u\) 到 \(v\) 的最短路径的边数。\(n\leq 10^5\)

solution

考虑求出每个点能到达的最远点,如果 \(k\) 超出这个范围则必然无解,否则在它到最远点的路径上任意截取 \(k\) 条边,取出向最远点走 \(k\) 条边到达的点。

使用换根 DP 求出最远点,使用倍增 LCA 求出树上 \(k\) 级祖先(查询一条链上走 \(k\) 步等价于从某个端点向上跳祖先)。\(O(n\log n)\)。

或是你发现这个所谓的最远点一定是直径两端点之一。于是随便拉一条直径,离线询问,以两端分别为根 dfs,同时维护一个祖先的栈。查询 \(k\) 级祖先就是看看栈中前 \(k\) 个访问到的祖先。

code

点击查看代码
// ubsan: undefined
// accoders
#include <cstdio>
#include <vector>
#include <cstring>
#include <cassert>
#include <algorithm>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
typedef long long LL;
int n, ans[1 << 18], Q;
vector<int> g[1 << 18];
vector<pair<int, int>> qry[1 << 18];
int stk[1 << 18], top = 0, hei[1 << 18];
int dfs(int u, int fa) {
    stk[++top] = u;
    for (auto q : qry[u]) {
        if (q.first < top)
            ans[q.second] = stk[top - q.first];
    }
    hei[u] = 0;
    int res = u;
    for (int v : g[u])
        if (v != fa) {
            int ret = dfs(v, u);
            if (hei[v] + 1 > hei[u])
                hei[u] = hei[v] + 1, res = ret;
        }
    --top;
    return res;
}
int main() {
    freopen("intoxicated.in", "r", stdin);
    freopen("intoxicated.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1, u, v; i < n; i++) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    scanf("%d", &Q);
    for (int i = 1, u, d; i <= Q; i++) {
        scanf("%d%d", &u, &d);
        qry[u].emplace_back(d, i);
    }
    memset(ans, -1, sizeof ans);
    hei[0] = 0;
    dfs(dfs(dfs(1, 0), 0), 0);
    for (int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
    return 0;
}


标签:intoxicated,int,题解,scanf,Exactly,祖先,Steps,include,最远
From: https://www.cnblogs.com/caijianhong/p/solution-abc267f.html

相关文章

  • Math teacher's homework 题解
    preface网上的题解看不懂,看代码看懂了:)solution考虑\(\mathrm{x_i}\)的倒数第\(\mathrm{low_i-1}\)位到倒数第\(\mathrm{1}\)位可以乱选(选\(\mathrm{0/1}\)都满足\(\mathrm{x_i\leqm_i}\)),那么就需要\(\mathrm{x_i}\)和\(\mathrm{m_i}\)的第\(\mathrm{1}\)位......
  • YACS 2023年9月月赛 甲组 题解
    题目链接1题目链接2题目链接3榜单终于公布了,这应该是第二长的榜单公布吧。(最长的一次是去年八月,拖到九月开始后才公布) T1是傻逼数据结构不说了吧,对于每个点枚举以他为角的$k\timesk$的四个正方形算一下点的数量,用$cdq$或者扫描线都行。看这个题目编号是$81$,看来是很......
  • 题解整理
    CF1740ACF1740BCF1740DCF1711BCF1253BCF1080BCF1237ACF1743ACF1743CCF1743BCF1370B......
  • P9744 消除序列 题解
    本题有多种解法,我这里先讲一个我的考场做法吧。切入点我们发现我们至多使用一次操作一,而剩下部分的\(0\)肯定是依靠操作二补全,操作三的作用只是用来填补操作一的空白的,所以我们发现我们对一个序列的操作一定是前一段用操作一和操作三,后一段用操作二。思路1一开始考虑暴力\(......
  • CEIT 23练习编程题 题解
    本文部分题目提供c/c++两种解法,顺便可以让你们知道c++在面对某些题时的优势部分题目提供多种解法日期格式化C#include<stdio.h>intmain(){intm,d,y;scanf("%d-%d-%d",&m,&d,&y);printf("%04d-%02d-%02d",y,m,d);return0;}02d的含义:当有效数......
  • 【题解】「KDOI-06-S」补题
    「KDOI-06-S」A.「KDOI-06-S」消除序列赛时写了一个\(O(nq)\)的线性DP,喜提60分。注意到如果操作1被使用,则一定只会使用一次,而且在最优策略中一定是第一次使用操作1。则我们可以通过以下方式进行操作,使序列满足条件:首先执行\(a_i\)和\(\sum^{j\lei,i\inP}_{j=......
  • [COCI2015-2016#4] ENDOR 题解
    [COCI2015-2016#4]ENDOR题解首先要发现一个很重要的性质,那就是两只变色龙碰撞后回头,等效于两只变色龙继续往前走,其中向右走的颜色不变,而向左走的要改变颜色。那这样就有一种\(O(n^2)\)的做法:对于向右的变色龙,直接贡献答案;对于向左的变色龙,我们按照碰到的先后顺序枚举它前面......
  • 【题解】AtCoder-ARC167
    AtCoder-ARC167AToastsforBreakfastParty一定不会有空盘,问题转化成\(2m\)个数,其中\(2m-n\)个是\(0\),这样一定是最大值和最小值一起,次大值和次小值一起,以此类推。提交记录:Submission-AtCoderAtCoder-ARC167BProductofDivisors\(A^B=\prod_ip_i^{Bc_i}\),那么答案......
  • CF1119F Niyaz and Small Degrees 题解
    原题翻译首先\(O(n^2\logn)\)的dp是simple的,我们设\(dp_{i,0/1}\)表示以\(i\)为根,\(i\)到\(fa_i\)这条边删/不删的最小权值和。转移是一个非常trick的问题,只需要假设所有都选\(dp_{i,0}\),然后把所有儿子按照\(dp_{v,1}+w(u,v)-dp_{v,0}\)排序,选前\(d......
  • P9745 「KDOI-06-S」树上异或 题解
    P9745「KDOI-06-S」树上异或题解\(x_i=0\)这题一看就不是很可做,先考虑部分分。对于一条链的情况,我们可以枚举上一个断边的位置,然后转移。一看数据范围,估计和值域有关,所以考虑\(x_i=1\)的部分分,如果全部点权都是1,那么一种方案只有0和1两种取值,考虑这个状态设计:\(f......