首页 > 其他分享 >ABC267F 题解

ABC267F 题解

时间:2024-08-03 11:05:58浏览次数:10  
标签:ABC267F fa int 题解 cin st dep dfs2

注意到,对于一棵树 \(T\) 的任一直径 \(a-b\),对于任意一点 \(u\),离 \(u\) 最远的点一定是 \(a\) 或 \(b\)。

考虑反证:如图,如果存在点 \(c\) 使得 \(dis(u,c)>\max(dis(u,a),dis(u,b))\)。

如图,\(a-b\) 为直径,\(d2>d1\)。因为有 \(d4>d3+d2\),所以有 \(d2+d3+d4>2d2+2d3>d1+d2\),所以 \(a-b\) 不是直径。

所以只要任找一条直径 \(x-y\),分别处理出以 \(x,y\) 为根时的倍增数组,询问时找到离自己更远的端点,倍增 \(k\) 步即可。

不存在输出 -1。

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

const int N = 2e5 + 5, K = 20;
vector<int> e[N];
int n, st[N][K], st2[N][K], d[N];

pair<int, int> dfs(int x, int fa)
{
    pair<int, int> ans = {0, x};
    for(int i : e[x])
    {
        if(i == fa) continue;
        auto t = dfs(i, x);
        t.first ++;
        ans = max(ans, t);
    }
    return ans;
}

int dep[N], dep2[N];
void dfs2(int x, int fa, int d, int dep[N], int st[N][K])
{
    dep[x] = d;
    st[x][0] = fa;
    for(int i = 1; i < K; i ++)
        st[x][i] = st[st[x][i - 1]][i - 1];
    for(int i : e[x])
    {
        if(i == fa) continue;
        dfs2(i, x, d + 1, dep, st);
    }
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> n;
    for(int i = 1; i < n; i ++)
    {
        int x, y; cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    int l = dfs(1, 0).second;
    int r = dfs(l, 0).second;
    dfs2(l, 0, 1, dep, st);
    dfs2(r, 0, 1, dep2, st2);
    int q; cin >> q;
    while(q --)
    {
        int x, k; cin >> x >> k;
        if(dep[x] > dep2[x])
        {
            for(int i = K - 1; i >= 0; i --)
                if((k >> i) & 1) x = st[x][i];
        }
        else
        {
            for(int i = K - 1; i >= 0; i --)
               if((k >> i) & 1) x = st2[x][i];
        }
        if(!x) cout << -1 << "\n";
        else cout << x << "\n";
    }

    return 0;
}

标签:ABC267F,fa,int,题解,cin,st,dep,dfs2
From: https://www.cnblogs.com/adam01/p/18340197

相关文章

  • ABC266F 题解
    输入的图是一颗基环树。对于\(x,y\),如果把环上的边去掉,得到的森林里\(x,y\)仍然在同一颗树内,那么显然只有一条路。否则一定要经过环,有两条路。于是dfs或着拓扑排序找环即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintN=2e5+......
  • 2024集训8.2模拟赛题解
    考试历程8:30开始考试8:40快速浏览了T1并想了一下,是一道质数的题目,准备打表,打到一半的时候发现空间复杂度会爆,于是改打质数筛暴力了9:30打完T1开始看T2刚开始没思路,先看了T3,跟着样例打了一点,估计可以拿点分吧9:50打完了T3会看T2发现了一点规律(后来知道是错的)跟着思路写了一......
  • gym105167E Erdős-Ginzburg-Ziv 题解
    题意:给\(p\)和\(p-1\)个边权,要用这些边权构造树,每个点编号\(0\simp-1\),使得每个点\(u\)到\(0\)的距离\(\bmod\p=u\),无解输出-1,保证\(p\)是质数、\(p\le10^6\)、边权\(\in[1..p-1]\).Solution考虑加边的过程,树最开始只有根节点0,然后通过加边不断地引入新的点......
  • 优秀的树 - 题解(数学)
    优秀的树时间限制:C/C++2000MS,其他语言4000MS内存限制:C/C++256MB,其他语言512MB描述给定一棵树,其所有边权重均为\(1\),定义\(f(u)=Σ_vdis(u,v)\),v表示树上的所有结点,\(dis(u,v)\)表示结点\(u\)和\(v\)的简单路径的长度。一棵树被称为“优秀”,当且仅当存在两个......
  • 【题解】走路
    I题意简述从原点出发,一步只能向右走、向上走或向左走。恰好走\(N\)步且不经过已走的点共有多少种走法?多组数据,每行输入一个数\(N\)。对于每一组测试数据,每行输出一个数,答案对\(12345\)取模。对于100%的数据,保证\(1\leqN\leq1000\)。时间限制\(1\text{s}\),空......
  • 树(tree) - 题解(带权并查集)
    树(tree)时间限制:C/C++2000MS,其他语言4000MS内存限制:C/C++256MB,其他语言512MB描述给定一个\(n\)个结点,\(n−1\)条边的有根树。第\(i\)条边可以用(\(a_i,b_i\))来描述,它表示连接结点\(a_i\)和结点\(b_i\)的一条边,其中结点\(a_i\)是结点\(b_i\)的父节点。......
  • Luogu P5005 中国象棋 - 摆上马 / Luogu P8756 国际象棋 题解 [ 蓝 ] [ 状压 dp ] [
    国际象棋:模板棋盘状压。摆上马:需要点思维的棋盘状压,相比上一道题加了“蹩马脚”的设定。Easy_version:国际象棋概述一下此类棋盘问题的思路:用二进制数表示出棋盘上某一行的状态。用位运算预处理出合法的单行状态,以及需要用到的一些东西。用位运算判断前一行或者前几行能否......
  • Luogu P3959 宝藏 题解 [ 紫 ] [ 状压 dp ] [ 二项式定理 ]
    宝藏:一个对着蓝书代码调都能调两个小时的大毒瘤,但是思路还是很值得借鉴的,有普通状压和三进制状压两种做法,或者暴搜剪枝也可以(这里不介绍暴搜剪枝做法)。普通状压做法观察到\(n\le12\),首先想到状压。但考虑到普通的状压不太行,因为\(K\)这个数算在代价里,会导致这个dp有后效......
  • BZOJ2839/LG10596 集合计数 题解(二项式反演+扩展欧拉定理)
    题目大意:一个有\(N\)个元素的集合有\(2^N\)个不同子集(包含空集),现在要在这\(2^N\)个集合中取出若干集合(至少一个),使得它们的交集的元素个数为\(K\),求取法的方案数,答案模\(10^9+7\)。为表述方便,不妨设这\(i\)个元素分别为\(1\simn\)。前置知识:二项式反演。考虑设\(g(......
  • 题解:CF1537E2 Erase and Extend (Hard Version)
    CF1537E2EraseandExtend题解分析通过观察题目,可以证明结果一定是由多次前缀复制得来的。题目要求你进行删和复制的操作,与其交替着操作,不如直接先删到最优的前缀再进行复制。现在就是要找最优的前缀。从头一位一位往后遍历。用\(l\)来存储目前最优前缀的长度,第\(i\)位......