小清新找性质题,想到关键就很简单
考虑在第一棵树上枚举一条从 \(1\) 到某个点的链,显然这些点之间满足第一个限制,现在只要在这些点中选出尽可能多的点满足第二个限制即可
在第二棵树上两个点没有祖先关系,等价于它们对应的 DFS 序区间相离
而两个点的 DFS 序区间显然要么相离要么包含,在出现包含的情况时舍去大的那个即可
用 set
维护区间,复杂度 \(O(n\log n)\)
#include<cstdio>
#include<iostream>
#include<set>
#include<vector>
#define RI register int
#define CI const int&
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
const int N=300005;
int t,n,x,ans,idx,L[N],R[N]; vector <int> A[N],B[N]; set <pi> s;
inline void DFS1(CI now=1)
{
L[now]=++idx; for (auto to:B[now]) DFS1(to); R[now]=idx;
}
inline void DFS2(CI now=1)
{
bool is_insert=0,is_delete=0; pi tmp;
auto it=s.lower_bound({L[now],0});
if (it!=s.end()&&it->se<R[now])
{
// don't insert this interval
} else
{
if (it!=s.begin())
{
--it;
if (it->fi<=L[now]&&R[now]<=it->se)
{
is_delete=1; tmp=*it;
s.erase(it);
}
}
is_insert=1; s.insert({L[now],R[now]});
}
ans=max(ans,(int)s.size());
for (auto to:A[now]) DFS2(to);
if (is_insert) s.erase({L[now],R[now]});
if (is_delete) s.insert(tmp);
}
int main()
{
for (scanf("%d",&t);t;--t)
{
scanf("%d",&n); ans=idx=0; s.clear();
for (RI i=1;i<=n;++i) A[i].clear(),B[i].clear();
for (RI i=2;i<=n;++i) scanf("%d",&x),A[x].push_back(i);
for (RI i=2;i<=n;++i) scanf("%d",&x),B[x].push_back(i);
DFS1(); DFS2(); printf("%d\n",ans);
}
return 0;
}
标签:insert,include,CF1528C,idx,int,Trees,Tranquillity,now,define
From: https://www.cnblogs.com/cjjsb/p/18359606