CF1528C Trees of Tranquillity

题目大意

给你两棵 n 个节点的树,要你找一个最大的点集 S,使得 S 中任意两点都满足:

  1. 在第一棵树上,两个点其中一个为另一个的祖先;
  2. 在第二棵树上,两个点互不为祖先关系。

思路

显然,我们选作为答案的点在第一棵树上的根到某一个叶子的链上。我们可以处理出第二棵树的欧拉序列(任意两个节点对应的进入时间与离开时间的区间要么完全包含要么完全不相交),我们在考虑加入一个点的时候,有以下两种情况:

  1. 如果之前的链上没有点的进入时间与离开时间的区间覆盖当前节点的进入时间与离开时间的区间,直接贪心加入。

  2. 如果有,保留小区间,删去大区间。

接下来就是如何实现问题。

首先是求第二棵树的欧拉序列。然后去遍历第一棵树,在线段树

中仅维护当前节点到根节点这些区间中合法的部分,然后统计答案。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 3e5 + 10, M = 3e5 + 10;

struct Seg_Tree {
    struct {
        int l, r;
        ll dat, tag;
    } t[M * 4];

    void build(int p, int l, int r) {
        t[p].l = l, t[p].r = r;
        t[p].tag = -114514;//因为tag=0时有用,所以要初始化成负数
        if
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值