CF1328E Tree Queries
CF1328E Tree Queries
应该还是比较妙的
题意
给你一个树,然后多次询问
每次询问给出一堆节点,问你是否能找到一个从根出发的链,是的对于给出的每个节点,都能找出链上的点,是的他们的距离小于等于\(1\)
\(n\leq 2\cdot 10^5,m\leq 2\cdot 10^5,\sum k\leq 2\cdot 10^5\)
其中\(m\)是询问次数,\(k\)是每次给出的点数
首先,一个点要想符合题目的条件,无非有两种情况
一种是就在链上,这个好说
另一种是距离链上的点距离为\(1\),那么,肯定是他的父亲在链上
所以,我们可以把每个给出的点转换成他的父亲,问题就变成看:能否找到一个链,是的这些点都在链上
这样的转换对第一种肯定是没有影响的,一个点在链上,他的父亲肯定也在链上
所以考虑转换后的问题
我首先想到的是,找出深度最大的节点,对于其它每个点和它求 LCA ,如果这个 LCA 不是那个深度较小的点,说明肯定连不成一个链
这一点判断基于那个链必须从根出发
然后写完代码交上去:
#100 WA!
emmm,估计是写炸了,第一个MLE是邻接表忘开2倍了
然而并没看出错,所以考虑一种实现更简单的方法
上面求 LCA 其实可以理解为从下向上考虑,那么还有一种从上往下考虑的方法:
先把每个点按深度从小到大排序,然后如果p[i+1]
不在p[i]
的子树里,那么肯定连不成一个链
至于怎么判断也很简单,记录一个dfs序和每个节点子树大小就行,具体见代码的check
函数
\(\texttt{code.}\)
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n,m;
int fir[200006],nex[400006],to[400006],tot;
int p[200006],fa[200006],size[200006];
int dfn[200006],deep[200006],dfscnt;
inline void add(int a,int b){
to[++tot]=b;
nex[tot]=fir[a];fir[a]=tot;
}
void dfs(int u,int fat){
fa[u]=fat;deep[u]=deep[fat]+1;dfn[u]=++dfscnt;size[u]=1;
for(reg int i=fir[u];i;i=nex[i])if(to[i]!=fat) dfs(to[i],u),size[u]+=size[to[i]];
}
inline int check(int a,int b){//看b是不是在a的子树
if(dfn[b]<dfn[a]) return 0;
if(dfn[b]>=dfn[a]+size[a]) return 0;
//这里一定是>=,如果dfn[b]=dfn[a]+size[a],也说明b并不在a的子树里,因为统计size[a]的时候a这个点也被算进去了
return 1;
}
inline int cmp(int x,int y){return deep[x]<deep[y];}
int main(){
n=read();m=read();
for(reg int a,b,i=1;i<n;i++){
a=read();b=read();
add(a,b);add(b,a);
}
reg int k;
dfs(1,1);
while(m--){
k=read();
for(reg int i=1;i<=k;i++) p[i]=fa[read()];
std::sort(p+1,p+1+k,cmp);
for(reg int i=2;i<=k;i++)
if(!check(p[i-1],p[i])) goto NO;
std::puts("YES");continue;
NO:;std::puts("NO");
}
return 0;
}
那个没A的LCA做法也放在这,也许哪天很闲的时候会再调调
记录
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n,m;
int fir[200006],nex[400006],to[400006],tot;
int p[200006];
int fa[23][200006],deep[200006];
inline void add(int a,int b){
to[++tot]=b;
nex[tot]=fir[a];fir[a]=tot;
}
void dfs(int u,int fat){
fa[0][u]=fat;deep[u]=deep[fat]+1;
for(reg int i=fir[u];i;i=nex[i])if(to[i]!=fat) dfs(to[i],u);
}
inline int check(int a,int b){
for(reg int i=20;~i;i--)
if(deep[fa[i][b]]>=deep[a]) b=fa[i][b];
return a==b;
}
int main(){
n=read();m=read();
for(reg int a,b,i=1;i<n;i++){
a=read();b=read();
add(a,b);add(b,a);
}
reg int k,maxdeep,maxdeepid;
dfs(1,1);
for(reg int i=1;i<=n;i++)
for(reg int j=1;j<=20;j++) fa[j][i]=fa[j-1][fa[j-1][i]];
while(m--){
k=read();maxdeep=0;
for(reg int i=1;i<=k;i++){
p[i]=fa[0][read()];
if(deep[p[i]]>maxdeep) maxdeep=deep[p[i]],maxdeepid=p[i];
}
for(reg int i=1;i<=k;i++)if(p[i]!=maxdeepid){
if(!check(p[i],maxdeepid)) goto NO;
}
std::puts("YES");continue;
NO:;std::puts("NO");
}
return 0;
}
CF1328E Tree Queries的更多相关文章
- E. Tree Queries 解析(思維、LCA)
Codeforce 1328 E. Tree Queries 解析(思維.LCA) 今天我們來看看CF1328E 題目連結 題目 給你一棵樹,並且給你\(m\le2e5\)個詢問(包含\(k\)個點) ...
- Codeforces 960D - Full Binary Tree Queries
960D - Full Binary Tree Queries 思路: 用move1[i]记录第i层第1种操作移动的个数(对这一层的个数取模) 用move2[i]记录第i层第2种操作移动的个数(对这一 ...
- AC日记——825G - Tree Queries
825G - Tree Queries 思路: 神题,路径拆成半链: 代码: #include <cstdio> #include <cstring> #include < ...
- CF-1328 E. Tree Queries
E. Tree Queries 题目链接 题意 给定一个树,每次询问一组点,问是否存在一条从根到某点的路径,使得该组点到该路径的最短距离不超过1 分析 从根到达某点的路径,如果覆盖到了某个点,那么一定 ...
- CF1254D Tree Queries(树链剖分)
出题人的做法是 \(O(n\sqrt{n\log n})\),结果这场结束后就被狂喷,一群人给出了 \(O(n\sqrt{n})\) 做法,甚至 \(O(n\log n)\) 都出来了-- 首先发现, ...
- Codeforces 960D Full Binary Tree Queries ( 思维 && 模拟 )
题意 : 给出一颗无限层的满二叉树,然后每个值为 X (根的 X 等于 1 ) 左孩子的值是 2*X,右孩子的值是 2*X+1 ,现在有两种操作,(1, x,k) 表示将 x 所在层的所有节点整体向右 ...
- CodeForces 825G"Tree Queries"(选根建树)
传送门 •参考资料 [1]:CodeForces 825G Educational Round #25 G :建树选根大法+O1大法+iostream解绑了还是慢 •题意 给定一颗包含 n 个节点的树 ...
- CF825G Tree Queries
[题意] 一棵树有 n个节点,初始均为白色,有两种操作: 1. 1 x 代表把结点 x 设置为黑色 2. 2 x 代表查询 x 到树上任意一个黑色结点的简单路径上的编号最小的结点的编号 输入 t 和 ...
- Codeforces 1606F - Tree Queries(虚树+树形 dp)
Codeforces 题面传送门 & 洛谷题面传送门 显然我们选择删除的点连同 \(u\) 会形成一个连通块,否则我们如果选择不删除不与 \(u\) 在同一连通块中的点,答案一定更优. 注意到 ...
随机推荐
- node+express+mysql实现简单的数据增删改查
前提 电脑已经安装了node,express,mysql. 实现步骤 1.新建数据库表 附数据表结构: 2.创建exprss项目 express -e myapp 新建一个以ejs为模板的expre ...
- TP的where方法的使用
1.Thinkphp中where()条件的使用 总是有人觉得,thinkphp的where()就是写我要进行增加.查询.修改.删除数据的条件,很简单的,其实我想告诉你,where()是写条件语句的,但 ...
- excel完成数据库数据的批量插入
业务场景: 开发过程中往往会遇到这样情况就是产品直接给我们一堆数据,让咱们直接导入到后台数据库中,这时候咱们只需要在excel表中进行直接操作即可,如图所示(以河北省的编号为例): 而对应的数据表为: ...
- 【高并发】高并发环境下如何防止Tomcat内存溢出?看完我懂了!!
写在前面 随着系统并发量越来越高,Tomcat所占用的内存就会越来越大,如果对Tomcat的内存管理不当,则可能会引发Tomcat内存溢出的问题,那么,如何防止Tomcat内存溢出呢?我们今天就来一起 ...
- java 第七周课后作业0417
定义一个矩形类Rectangle:(知识点:对象的创建和使用)1 定义三个方法:getArea()求面积.getPer()求周长,showAll()分别在控制台输出长.宽.面积.周长.2 有2个属性: ...
- XFS文件系统的备份与恢复
永久修改主机名:hostnamectl set-hostname oldboy临时修改主机名:hostname xfsdump备份xfsdump -f 备份的文件位置 要备份的分区或者磁盘 免交互备份 ...
- Some Modern Softwares' drawbacks: User experience 12/29/2015
In the nowadays, there are many APP in the PC or smart Phone. Some of them can't meet the customers' ...
- Linux服务器压力测试总结(CPU、Memory、IO等)
测试工具:sysbench.memtester.htop 1.htop安装使用 yum install ncurses-devel # 安装依赖包 tar zxvf htop-2.2.0.tar.gz ...
- Linux学习笔记(八)权限管理命令
权限管理命令 权限位含义 chmod chown chgrp umask默认权限 权限位含义 第1位代表文件类型 "-":普通文件 "b":块设备文件 &quo ...
- 【半译】在ASP.NET Core中创建内部使用作用域服务的Quartz.NET宿主服务
在我的上一篇文章中,我展示了如何使用ASP.NET Core创建Quartz.NET托管服务并使用它来按计划运行后台任务.不幸的是,由于Quartz.NET API的工作方式,在Quartz作业中使用 ...