题面

有两棵

n

n

n 个点的有根树

T

1

T_1

T1​,

T

2

T_2

T2​,根是

1

1

1 ,共用编号

1

1

1~

n

n

n。求最大的点集

S

S

S 满足每个点在

T

1

T_1

T1​ 中一条到根的链上,且任意两个点在

T

2

T_2

T2​ 中没有祖先关系

输出该点集的大小,

t

t

t 组数据。

1

t

3

×

1

0

5

,

2

n

3

×

1

0

5

,

n

3

×

1

0

5

1\leq t\leq3\times10^5~,~2\leq n\leq 3\times 10^5~,~\sum n\leq 3\times 10^5

1≤t≤3×105 , 2≤n≤3×105 , ∑n≤3×105

题解

题面我已经转化了一部分了,继续转化:

我们处理出每个点在

T

2

T_2

T2​ 中的

d

f

s

\rm dfs

dfs 序,记为

d

f

n

[

i

]

{\rm dfn}[i]

dfn[i],并求出每个点在

T

2

T_2

T2​ 的子树内节点(包括自己)

d

f

n

[

j

]

{\rm dfn}[j]

dfn[j] 的范围,记为

[

l

i

,

r

i

]

[l_i,r_i]

[li​,ri​] ,不妨称它为点

i

i

i 的区间。

那么一个集合

S

S

S 可行,等价于集合中的点在

T

1

T_1

T1​ 一条到跟的链上,且集合中每个点的区间两两无交集

我们还可以发现一些性质:每两个点的区间要么无交集,要么存在包含关系,且一个左端点只对应一个右端点。那么我们就可以想出一个贪心策略:互相包含的区间,取较小的保留。把它挪回树上,其实就相当于存在一个点的子孙可选的时候该点不选最优一样。

接下来就简单了。我们只需要从

T

1

T_1

T1​ 的根开始往下

d

f

s

\rm dfs

dfs ,每到一个点往某数据结构中加入自己的区间:

  • 如果被数据结构中原有的更大区间包含了,那么把那个大区间删掉,把自己加进去。
  • 如果包含了数据结构中原有的至少一个小区间,那么不加自己。
  • 否则,把自己加入进去,此时数据结构大小(即答案)+1。

然后遍历儿子。

回溯的时候数据结构要退回来时的状态。

具体用的数据结构就五花八门了,比较懒的可以直接用 set 之类,稍微比较聪明的可以打打树状数组或常数优秀的 zkw 线段树(有的人利用了两棵树中父亲编号小于儿子编号的特性,打出最优秀的三行朴素树状数组跑了

R

a

n

k

1

\rm Rank~1

Rank 1)。

CODE

下面是个比较好看懂的 set 代码

#include<set>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 300005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
#define SI set<int>::iterator
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
vector<int> g0[MAXN];
int L[MAXN],R[MAXN],lR[MAXN],tim;
void dfs0(int x,int ff) {
L[x] = ++ tim;
for(int i = 0;i < (int)g0[x].size();i ++) {
if(g0[x][i] != ff) dfs0(g0[x][i],x);
}R[x] = tim; lR[L[x]] = R[x];
return ;
}
vector<int> g[MAXN];
int d[MAXN],dfn[MAXN],rr[MAXN],cnt,ans;
set<int> st;
void dfs(int x,int ff) {
int ad = 0;
if(st.empty()) st.insert(L[x]);
else {
SI i = st.lower_bound(L[x]);
if(i != st.begin()) {
i --;
if(lR[*i] >= R[x]) ad = *i,st.erase(ad),st.insert(L[x]);
else {
i ++;
if(i == st.end() || *i > R[x]) st.insert(L[x]);
}
}
else if(i == st.end() || *i > R[x]) st.insert(L[x]);
}
ans = max(ans,(int)st.size());
for(int i = 0;i < (int)g[x].size();i ++) {
if(g[x][i] != ff)
dfs(g[x][i],x);
}
if(st.find(L[x]) != st.end()) st.erase(L[x]);
if(ad) st.insert(ad);
return ;
}
int main() {
int T = read();
while(T --) {
n = read();
tim = 0; cnt = 0;
st.clear();
for(int i = 1;i <= n;i ++) {
g0[i].clear();g[i].clear();lR[i] = 0;
}
for(int i = 2;i <= n;i ++) {
s = read(); g[s].push_back(i);
}
for(int i = 2;i <= n;i ++) {
s = read(); g0[s].push_back(i);
}
dfs0(1,0);ans = 0;dfs(1,0);
printf("%d\n",ans);
}
return 0;
}

CF1528C Trees of Tranquillity(图论,数据结构)的更多相关文章

  1. [ An Ac a Day ^_^ ] hdu 1662 Trees on the level 数据结构 二叉树

    紫书上的原题 正好学数据结构拿出来做一下 不知道为什么bfs的队列一定要数组模拟…… 还可以练习一下sscanf…… #include<stdio.h> #include<iostr ...

  2. 图论&数据结构——并查集

    Wikioi 4246 NOIP模拟赛Day2T1 奶牛的身高  题目描述 Description 奶牛们在FJ的养育下茁壮成长.这天,FJ给了奶牛Bessie一个任务,去看看每个奶牛场中若干只奶牛的 ...

  3. 2021record

    2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...

  4. Noip 训练指南

    目录 Noip 训练指南 图论 数据结构 位运算 期望 题解 Noip 训练指南 目前完成 \(4 / 72\) 图论 [ ] 跳楼机 [ ] 墨墨的等式 [ ] 最优贸易 [ ] 泥泞的道路 [ ] ...

  5. TokuDB性能测试报告

    一 .背景介绍 近年来,TokuDB作为MySQL的大数据(Big Data)存储引擎受到人们的普遍关注.其架构的核心基于一种新的叫做分形树(Fractal Trees)的索引数据结构,该结构是缓存无 ...

  6. Disruptor——一种可替代有界队列完成并发线程间数据交换的高性能解决方案

    本文翻译自LMAX关于Disruptor的论文,同时加上一些自己的理解和标注.Disruptor是一个高效的线程间交换数据的基础组件,它使用栅栏(barrier)+序号(Sequencing)机制协调 ...

  7. NOIP考点

    NOIP考点 基础算法 图 树 数论 数据结构 动态规划 搜索 其他算法 省选知识点汇总 图论 数据结构 字符串相关算法及数据结构 数学 计算几何 搜索 动态规划 其他算法 转自:巨佬的博客 加*号是 ...

  8. Luogu P3783 [SDOI2017]天才黑客

    题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...

  9. Marked Ancestor [AOJ2170] [并查集]

    题意: 有一个树,有些节点染色,每次有两种操作,第一,统计该节点到离它最近的染色父亲结点的的号码(Q),第二,为某一个节点染色(M),求第一种操作和. 输入: 输入由多个数据集组成.每个数据集都有以下 ...

随机推荐

  1. JMeter - 生成随机数/随机字符串/随机变量/随机日期

    1. Random - 随机数 1.1 作用 1.2 声明 1.3 例子 2. __RandomDate - 随机日期 2.1 作用 2.2 声明参数 2.3 例子 3. RandomString - ...

  2. 【生成对抗网络学习 其三】BiGAN论文阅读笔记及其原理理解

    参考资料: 1.https://github.com/dragen1860/TensorFlow-2.x-Tutorials 2.<Adversarial Feature Learning> ...

  3. 【Redis】ziplist压缩列表

    压缩列表 压缩列表是列表和哈希表的底层实现之一: 如果一个列表只有少量数据,并且数据类型是整数或者比较短的字符串,redis底层就会使用压缩列表实现. 如果一个哈希表只有少量键值对,并且每个键值对的键 ...

  4. C语言学习之我见-strncpy()字符串复制函数(可控制范围)

    strncpy()函数,用于两个字符串值的复制. (1)函数原型 char *strncpy(char * _Dest,const char * _Source,size_t _Count); (2) ...

  5. JS:条件语句1

    条件语句: 1.if...else if (condition1) { 当条件 1 为 true 时执行 } else { 当条件 1 不为 true 时执行 } if (condition1) { ...

  6. raid划分及创建

    RAID 的划分 RAID 0 - RAID 0是最早出现的,是数据分条技术.组建磁盘阵列中最简单的一种形式,可以提高整个磁盘的性能和吞吐量,利用率100%,缺点:一但磁盘损坏,raid0将失效,数据 ...

  7. 国外价值10K+美金的Python面试题,珍藏已久,含泪放了出来

    兄弟们,没吹牛皮,一哥们在国外面试的时候,就是要他做的这个,直接给他说,做出来了给你15K(单位是刀),做不出来就拜拜~ 大兄弟当时就不服了,这不是看不起我么,分分钟就给整完了~ 我上我也行系列: 唠 ...

  8. Day04 HTML标记

    路径 ./ 同级目录 ./ 进入该目录名下 ../ 上一级目录 HTML标记 图片 <!-- 图片标记 src 图片的路径 width 设置图片宽度 height 设置图片高度 title 鼠标 ...

  9. 低代码如何构建支持OAuth2.0的后端Web API

    OAuth2.0 OAuth 是一个安全协议,用于保护全球范围内大量且不断增长的Web API.它用于连接不同的网站,还支持原生应用和移动应用于云服务之间的连接,同时它也是各个领域标准协议中的安全层. ...

  10. Windows 远程连接后,自动断开,所有程序都自动关闭(待验证,待更新)

    win+r输入regedit打开注册表编辑SecurityLayer,将值改为2 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Ter ...