当前位置: 首页 > news >正文

Good Bye 2013 F. New Year Tree 倍增、思维

题目链接

题目大意

初始有一颗4个顶点的数, 1 1 1号点的度数为 3 3 3 2 2 2 4 4 4 号点为叶子结点。 q q q ( 1 ≤ q ≤ 5 ∗ 1 0 5 ) (1 \leq q \leq 5*10^5) (1q5105)次操作,每次操作如下:

  • 首先,选择树中编号为 v v v的叶子结点。
  • n n n表示此刻树上的结点数,然后向树上添加两个顶点,编号分别为 n + 1 n+1 n+1 n + 2 n+2 n+2,同时得到新的边,一条在 v v v n + 1 n+1 n+1之间,另一条在 v v v n + 2 n+2 n+2之间。
    每次询问输出当前树的直径。

思路

首先,树的直径一定是叶子结点到叶子结点。

设当前直径为 d 1 d_1 d1 d 2 d_2 d2,若添加一个叶子结点 v v v,直径的变化有三种情况: ( 1 ) 、 (1)、 (1)保持不变仍为 d 1 d_1 d1 d 2 d_2 d2 ( 2 ) 、 (2)、 (2)变为 v v v d 1 d_1 d1 ( 3 ) 、 (3)、 (3)变为 v v v d 2 d_2 d2 。只需要每次加入点都看看这三种情况,取一个最大的即可。

计算直径的大小可以借助 l c a lca lca来计算, u u u v v v的距离 d = d= d= d e e p t h ( u ) + d e e p t h ( v ) − 2 ∗ d e e p t h ( l c a ( u , v ) ) deepth(u)+deepth(v)-2*deepth(lca(u,v)) deepth(u)+deepth(v)2deepth(lca(u,v)).

code

#include <bits/stdc++.h>
#define ll long long
#define pii pair<int, int>

using namespace std;
const int N = 5e5 + 10, M = N * 2;
int deepth[M], anc[M][21];
vector<int> a[M];
int d[2] = {2, 3}, t[2];

void dfs(int x, int fa)
{
    deepth[x] = deepth[fa] + 1;
    anc[x][0] = fa;
    for (int i = 1; i < 21; ++i)
        anc[x][i] = anc[anc[x][i - 1]][i - 1];
    for (auto k : a[x])
    {
        if (k == fa)
            continue;
        dfs(k, x);
    }
}

int lca(int a, int b)
{
    if (deepth[a] < deepth[b])
        swap(a, b);
    for (int i = 20; i >= 0; --i)
        if (deepth[anc[a][i]] >= deepth[b])
            a = anc[a][i];
    if (a == b)
        return b;
    for (int i = 20; i >= 0; --i)
    {
        if (anc[a][i] != anc[b][i])
        {
            a = anc[a][i];
            b = anc[b][i];
        }
    }
    return anc[a][0];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int idx = 2;
    for (int i = 0; i < 3; ++i)
    {
        a[1].push_back(idx);
        a[idx++].push_back(1);
    }
    dfs(1, 0);
    int len = 2;
    int q;
    cin >> q;
    for (int i = 0; i < q; ++i)
    {
        int x;
        cin >> x;
        t[0] = idx, t[1] = idx + 1;
        a[x].push_back(idx);
        a[idx].push_back(x);
        dfs(idx, x);
        idx++;
        a[x].push_back(idx);
        a[idx].push_back(x);
        dfs(idx, x);
        idx++;
        for (int j = 0; j < 2; ++j)
            for (int k = 0; k < 2; ++k)
            {
                int tmp1 = lca(t[j], d[k]);
                int tmp2 = deepth[t[j]] + deepth[d[k]] - deepth[tmp1] * 2;
                if (tmp2 > len)
                {
                    len = tmp2;
                    d[1 - k] = t[j];
                }
            }
        cout << len << '\n';
    }
    return 0;
}

相关文章:

  • 原函数存在定理
  • 一个基于C语言的猜数字小游戏
  • 【打卡day3】字符串类
  • clickhouse查询效率低
  • C++之list
  • SpringBoot POST和GET请求
  • 【算法】大数据查重
  • 庞加莱映射的性质
  • vs code 设置字体颜色
  • 深入了解蓝牙广播与扫描响应
  • Codeforces Round 258 (Div. 2) E. Devu and Flowers 生成函数
  • 四、云原生应用监控-Etcd
  • IMX6ULL的最简单的LED驱动程序
  • 南开提出1Prompt1Story,无需训练,可通过单个连接提示实现一致的文本到图像生成。
  • 掌握Linux基础:从文件链接到Shell命令的全面指南
  • CTF杂项——[WUSTCTF 2020]alison_likes_jojo
  • React:类组件(上)
  • 开发、科研、日常办公工具汇总(持续更新)
  • matlab常见的配图代码实现1
  • SpringBatch之ResultSet.next()
  • 中国需加强自主创新和国际合作,提升产业链供应链韧性
  • 每一笔都是对的!再读周碧初画作有感
  • 国家话剧院上海演出季7月重启,《大宅门》等5部大戏来沪
  • 前4个月全国新建商品房销售面积降幅收窄,房地产库存和新开工有所改善
  • 海南乐城管理局原局长贾宁已赴省政协工作,曾从河南跨省任职
  • 全球前瞻|特朗普19日将与俄乌总统分别通话,英国脱欧后首开英欧峰会