首页 > 其他分享 >G. Sakurako and Chefir

G. Sakurako and Chefir

时间:2024-10-25 17:45:46浏览次数:1  
标签:f1 le int Chefir vertex Sakurako 子树

G. Sakurako and Chefir

Given a tree with $n$ vertices rooted at vertex $1$. While walking through it with her cat Chefir, Sakurako got distracted, and Chefir ran away.

To help Sakurako, Kosuke recorded his $q$ guesses. In the $i$-th guess, he assumes that Chefir got lost at vertex $v_i$ and had $k_i$ stamina.

Also, for each guess, Kosuke assumes that Chefir could move along the edges an arbitrary number of times:

from vertex $a$ to vertex $b$, if $a$ is an ancestor$^{\text{∗}}$ of $b$, the stamina will not change;

from vertex $a$ to vertex $b$, if $a$ is not an ancestor of $b$, then Chefir's stamina decreases by $1$.

If Chefir's stamina is $0$, he cannot make a move of the second type.

For each assumption, your task is to find the distance to the farthest vertex that Chefir could reach from vertex $v_i$, having $k_i$ stamina.

$^{\text{∗}}$Vertex $a$ is an ancestor of vertex $b$ if the shortest path from $b$ to the root passes through $a$.

Input

The first line contains a single integer $t$ ($1\le t\le 10^4$) — the number of test cases.

Each test case is described as follows:

  • The first line contains a single integer $n$ ($2 \le n \le 2 \cdot 10^5$) — the number of vertices in the tree.
  • The next $n-1$ lines contain the edges of the tree. It is guaranteed that the given edges form a tree.
  • The next line consists of a single integer $q$ $(1\le q\le 2 \cdot 10^5)$, which denotes the number of guesses made by Kosuke.
  • The next $q$ lines describe the guesses made by Kosuke, with two integers $v_i$, $k_i$ $(1\le v_i \le n, 0 \le k_i\le n)$.

It is guaranteed that the sum of $n$ and the sum of $q$ across all test cases does not exceed $2\cdot 10^5$.

Output

For each test case and for each guess, output the maximum distance to the farthest vertex that Chefir could reach from the starting point $v_i$ having $k_i$ stamina.

Example

Input

3
5
1 2
2 3
3 4
3 5
3
5 1
3 1
2 0
9
8 1
1 7
1 4
7 3
4 9
3 2
1 5
3 6
7
6 0
2 3
6 2
8 2
2 4
9 2
6 3
6
2 1
2 5
2 4
5 6
4 3
3
3 1
1 3
6 5

Output

2 1 2 
0 5 2 4 5 5 5 
1 3 4 

Note

In the first example:

  • In the first query, you can go from vertex $5$ to vertex $3$ (after which your stamina will decrease by $1$ and become $0$), and then you can go to vertex $4$;
  • In the second query, from vertex $3$ with $1$ stamina, you can only reach vertices $2$, $3$, $4$, and $5$;
  • In the third query, from vertex $2$ with $0$ stamina, you can only reach vertices $2$, $3$, $4$, and $5$;

 

解题思路

  赛时没留意到 $k$ 是任意取值从而 $v$ 可能往上跳出根节点,导致没处理越界情况 WA 麻了。发现后对 $k$ 与 $v$ 到根节点距离取最小值就过了,还以为写了个假做法。

  定义 $d_v$ 表示节点 $v$ 的深度(规定根节点 $d_1 = 1$)。由于往父节方向点走会消耗 $1$ 点体力,因此 $v$ 最多往上走到距离其 $\min\{k, d_v - 1\}$ 的祖先,记为 $P$。由于往下走不消耗体力,因此从 $v$ 出发能走到子树 $P$(以 $P$ 为根的子树)中的任意一点,同时这也是从 $v$ 出发消耗体力不超过 $k$ 所能到达的所有点。所以距离 $v$ 最远的点只能在子树 $P$ 中找。

  我们知道树中任意两点 $u,v$ 构成路径的长度可以表示成 $d_u + d_v - 2 \cdot \mathrm{lca}(u, v)$。设 $u$ 是子树 $P$ 中的节点,将 $u$ 与 $v$ 构成的路径按最近公共祖先进行分类,那么这些最近公共祖先均是距离 $v$ 不超过 $\min\{k, d_v - 1\}$ 的祖先。假设 $p'$ 是 $v$ 的祖先,$p$ 是 从 $p'$ 再往上走一步的祖先,显然 $p'$ 是 $p$ 的子节点。$u$ 和 $v$ 的最近公共祖先是 $p$ 当且仅当 $u$ 是子树 $p$ 中的节点且不在子树 $p'$ 中,如下图所示。

  定义 $f_1(u)$ 表示子树 $u$ 中到 $u$ 的最大距离,$f_2(u)$ 表示子树 $u$ 中到 $u$ 的次大距离。依次枚举 $v$ 的祖先 $p$,那么在子树 $p$ 且与 $v$ 构成的最近公共祖先是 $p$ 的节点中,到 $v$ 的最大距离就是 $\displaylines{\begin{cases}f_2(p) + d_v - d_p, &f(p') + 1 = f(p) \\ f_1(p) + d_v - d_p, &f(p') + 1 \ne f(p) \end{cases}}$。可以考虑倍增优化这个枚举过程。

  定义 $\mathrm{fa}(u,i)$ 表示从 $u$ 往上走 $2^i$ 步到达的节点。$g(u,i)$ 表示距离 $u$ 不超过 $2^i$ 的每个祖先 $p$ 中(不含 $u$)关于 $f_1(p) - d_p$ 或 $f_2(p) - d_p$ 的最大值(即对于每个 $p$ 只考虑在子树 $p$ 且与 $u$ 构成的最近公共祖先是 $p$ 的节点)。状态转移方程就是

\begin{cases}
g(u,i) = \displaylines{\begin{cases}f_2(p_u) - d_{p_u}, &f(u) + 1 = f(p_u) \\ f_1(p_u) - d_{p_u}, &f(u) + 1 \ne f(p_u) \end{cases}} \, , &i=0  \\\\
g(u,i) = \max\{ g(u,i-1), \, g\left(\mathrm{fa}(u,i-1), i-1\right) \} \, , &i > 0
\end{cases}

  其中 $p_u = fa(u,0)$ 是 $u$ 的父节点。$g(u,i) + d_v$ 就是距离 $u$ 不超过 $2^i$ 的祖先所构成的子树中,距离 $v$ 的最大距离。

  最后对于每个询问 $v$ 和 $k$,先处理越界问题,即 $k \gets \min\{ k, d_v - 1 \}$。记 $t = d_v$,然后枚举 $k$ 的二进制的每一位,如果第 $i$ 位是 $1$ 就往上跳 $2^i$ 步,同时将答案与 $g(v,i) + t$ 取最大值,并置 $v \gets fa(v, i)$。

  AC 代码如下,时间复杂度为 $O((n + q) \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 5, M = N * 2;

int h[N], e[M], ne[M], idx;
int d[N], f1[N], f2[N];
int fa[N][18], g[N][18];

void add(int u, int v) {
    e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}

void dfs1(int u, int p) {
    d[u] = d[p] + 1;
    f1[u] = f2[u] = 0;
    for (int i = h[u]; i != -1; i = ne[i]) {
        int v = e[i];
        if (v == p) continue;
        dfs1(v, u);
        int t = f1[v] + 1;
        if (t > f1[u]) f2[u] = f1[u], f1[u] = t;
        else if (t > f2[u]) f2[u] = t;
    }
}

void dfs2(int u, int p) {
    fa[u][0] = p;
    if (f1[p] == f1[u] + 1) g[u][0] = f2[p] - d[p];
    else g[u][0] = f1[p] - d[p];
    for (int i = 1; i <= 17; i++) {
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
        g[u][i] = max(g[u][i - 1], g[fa[u][i - 1]][i - 1]);
    }
    for (int i = h[u]; i != -1; i = ne[i]) {
        int v = e[i];
        if (v == p) continue;
        dfs2(v, u);
    }
}

void solve() {
    int n, m;
    cin >> n;
    idx = 0;
    memset(h, -1, n + 1 << 2);
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        add(u, v), add(v, u);
    }
    dfs1(1, 0);
    dfs2(1, 0);
    cin >> m;
    while (m--) {
        int x, k;
        cin >> x >> k;
        k = min(k, d[x] - 1);
        int ret = f1[x], t = d[x];
        for (int i = 0; i <= 17; i++) {
            if (k >> i & 1 && x) {
                ret = max(ret, g[x][i] + t);
                x = fa[x][i];
            }
        }
        cout << ret << ' ';
    }
    cout << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round 981 (Div. 3) - Codeforces:https://codeforces.com/blog/entry/135421

标签:f1,le,int,Chefir,vertex,Sakurako,子树
From: https://www.cnblogs.com/onlyblues/p/18502986

相关文章

  • Codeforces Round 970 (Div. 3) D. Sakurako‘s Hobby
     链接cf_Sakurako‘sHobby大意:给一堆点和边,并给出点的颜色,输出每个点能遍历到几个黑点思路:1、这些点边里面有拓扑结构,也有环2、先处理拓扑排序的一些点,依次遍历无父节点的即可,之后就会剩下环3、有环的说明每个点都能去到环内任意一点,那么直接就记录一个sum,然后递归......
  • F. Sakurako's Box
    原题链接题意给定一个数组,随机取两个数并相乘,求该期望分析暴力方法:遍历所有数对,然后累加,最后除以数对个数\(O(n^2)\)每个数的贡献为\(\suma_j,j\in[1,n],j\nei\),遍历计算每个数对最后累加和的贡献由于要去重,所以每个数的贡献只统计前面的数的和\(O(n)\)code#include......
  • D. Sakurako's Hobby
    原题链接题意每个数要么黑色,要么白色,每个数都有跳往下一个数,请问你最多能得到几个黑色数?分析前往下一个数具有很强的指示性,所以我们可以画一个有向图出来那么问题就变成了一个有向图,问图中的每个点最多能到达几个黑色的点?(只有一个出边)但是注意本题,由于是排列,每个点最多只有......
  • G. Sakurako's Task
    https://codeforces.com/contest/2008/problem/G总结:一开始思路错了,考虑的只有n=1和g=1,还有其他情况。其实情况应该分为其他三种:n=1,n个数之间的所有空缺都能被填完(并且k仍剩余可以继续往后填),n个数之间的空缺不能被填完三种情况。inlinevoidsolve(){ intn,k; cin>>......
  • H. Sakurako's Test
    H.Sakurako'sTestSakurakowillsoontakeatest.Thetestcanbedescribedasanarrayofintegers$n$andataskonit:Givenaninteger$x$,Sakurakocanperformthefollowingoperationanynumberoftimes:Chooseaninteger$i$($1\lei\len$......