题目大意
给你两棵 n 个节点的树,要你找一个最大的点集 S,使得 S 中任意两点都满足:
- 在第一棵树上,两个点其中一个为另一个的祖先;
- 在第二棵树上,两个点互不为祖先关系。
思路
显然,我们选作为答案的点在第一棵树上的根到某一个叶子的链上。我们可以处理出第二棵树的欧拉序列(任意两个节点对应的进入时间与离开时间的区间要么完全包含要么完全不相交),我们在考虑加入一个点的时候,有以下两种情况:
-
如果之前的链上没有点的进入时间与离开时间的区间覆盖当前节点的进入时间与离开时间的区间,直接贪心加入。
-
如果有,保留小区间,删去大区间。
接下来就是如何实现问题。
首先是求第二棵树的欧拉序列。然后去遍历第一棵树,在线段树
中仅维护当前节点到根节点这些区间中合法的部分,然后统计答案。
#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