Luogu P3806 点分治模板1
题意:
给定一棵有n个点的树询问树上距离为k的点对是否存在。
分析:
这个题的询问和点数都不多(但是显然暴力是不太好过的,即使有人暴力过了)
这题应该怎么用点分治呢。显然,一个模板题,我们直接用套路,每次找重心,对于这个重心处理,过当前点的符合要求的路径。
我们可以看到这个最大长度1e7,开数组是开得下的,所以维护一个数组(或者bitset也行)来保存之前的子树中到根距离的长度,之后访问到每个子树时,先查询,再记录,最后删除标记,将所有的点都统计完之后,答案便被保存到了数组中,直接按照题意输出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=,inf=1e7;
struct node{int y,z,nxt;}e[N<<];
int n,m,c=,h[N],mx[N],siz[N],d[N],rem[N],sm;
int t[inf],jd[inf],vis[N],que[N],q[N],rt,ans;
void add(int x,int y,int z){
e[++c]=(node){y,z,h[x]};h[x]=c;
e[++c]=(node){x,z,h[y]};h[y]=c;
} void getrt(int x,int fa){//负责找重心
siz[x]=;mx[x]=;
for(int i=h[x],y;i;i=e[i].nxt)
if((y=e[i].y)!=fa&&!vis[y]){
getrt(y,x);siz[x]+=siz[y];
mx[x]=max(mx[x],siz[y]);
} mx[x]=max(mx[x],sm-siz[x]);
if(mx[x]<mx[rt]) rt=x;return ;
} void dfs(int x,int fa){//负责求点到子树中点的距离
rem[++rem[]]=d[x];
for(int i=h[x],y;i;i=e[i].nxt)
if((y=e[i].y)!=fa&&!vis[x])
d[y]=d[x]+e[i].z,dfs(y,x);
} void calc(int x){ int p=;//负责处理x点为根的子树
for(int i=h[x],y;i;i=e[i].nxt)
if(!vis[y=e[i].y]){
rem[]=;d[y]=e[i].z;dfs(y,x);
for(int j=rem[];j;j--)
for(int k=;k<=m;k++)
if(que[k]>=rem[j])
t[k]|=jd[que[k]-rem[j]];
for(int j=rem[];j;j--)
q[++p]=rem[j],jd[rem[j]]=;
} for(int i=;i<=p;i++) jd[q[i]]=;
} void solve(int x){//负责每次找重心,层层分治
vis[x]=jd[]=;calc(x);
for(int i=h[x],y;i;i=e[i].nxt){
if(vis[y=e[i].y]) continue;
sm=siz[y];mx[rt=]=inf;
getrt(y,);solve(rt);
} return;
} int main(){
scanf("%d%d",&n,&m);
for(int i=,x,y,z;i<n;i++)
scanf("%d%d%d",&x,&y,&z),add(x,y,z);
for(int i=;i<=m;i++) scanf("%d",&que[i]);
mx[rt]=sm=n;getrt(,);solve(rt);
for(int i=;i<=m;i++)
if(t[i]) puts("AYE");else puts("NAY");
return ;
}
点分治
Luogu P3806 点分治模板1的更多相关文章
- 【Luogu】P3806点分治模板(点分治)
题目链接 wc听不懂lca讲的高等数学专场(一个字都听不懂),然后就自学了点分治. 点分治就是我先处理完跟根有关的东西,然后把根标记掉,把原树拆成若干个联通块,然后分别对每个联通块(每个小树)搞一模一 ...
- 洛谷 P3806 点分治模板
题目:https://www.luogu.org/problemnew/show/P3806 就是点分治~ 每次暴力枚举询问即可,复杂度是 nmlogn: 注意 tmp[0]=1 ! 代码如下: #i ...
- 模板·点分治(luogu P3806)
[模板]洛谷·点分治 1.求树的重心 树的重心:若A点的子树中最大的子树的size[] 最小时,A为该树的中心 步骤: 所需变量:siz[x] 表示 x 的子树大小(含自己),msz[x] 表示 其子 ...
- [luogu P3806] 【模板】点分治1
[luogu P3806] [模板]点分治1 题目背景 感谢hzwer的点分治互测. 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在. 输入输出格式 输入格式: n,m 接下来n-1条 ...
- (模板)luoguP3806(树上点分治模板题)
点分治的写法1: 题目链接:https://www.luogu.org/problem/P3806 题意:给出一颗带边权的树,结点数n<=1e4,每条边有权值<=1e4,有m组询问(m&l ...
- Luogu 3806 点分治1
Luogu 3806 点分治 要分清楚各个函数的作用及互相调用的关系. 因为是无根树,找重心的时候,父亲一边的所有节点也可以看做是一颗子树. #include<bits/stdc++.h> ...
- [Luogu 3701] 「伪模板」主席树
[Luogu 3701] 「伪模板」主席树 这是一道网络流,不是主席树,不是什么数据结构,而是网络流. 题目背景及描述都非常的暴力,以至于 Capella 在做此题的过程中不禁感到生命流逝. S 向 ...
- 洛谷P2634 [国家集训队]聪聪可可 点分治模板
题意 在一棵树上任意选两个点,求它们距离模3为0的概率. 分析 树分治模板 Code #include<bits/stdc++.h> #define fi first #define se ...
- POJ1741 tree (点分治模板)
题目大意: 给一棵有 n 个顶点的树,每条边都有一个长度(小于 1001 的正整数).定义 dist(u,v)=节点 u 和 v 之间的最小距离.给定一个整数 k,对于每一对 (u,v) 顶点当且仅当 ...
随机推荐
- D3.js 线段生成器 (V3版本)
线段生成器 与线段生成器相关的方法: d3.svg.line() //创建一个线段生成器. line(data) //使用线段生成器绘制data数据. line.x([x]) //设置或获取线 ...
- 如何使用go打出hell word
今天给大家带来一篇如何使用go打出hell word(手动滑稽) 关于go介绍的话,我就不多说了,在百度上一搜一大堆, 要使用的软件Visual Studio Code(VScode) 下载go的地址 ...
- inline-block元素水平居中问题
今天做项目的时候碰到了不固定元素个数,需要水平居中的问题,原来的确定宽度下margin:0 auto等方法木有用了.想起来之前看过display:inline-block的文章, 果断用这个. 之前很 ...
- Linux 命令与学习
2014-10-10 ps -ef|grep *** 可以查找包含***名称的进程 netstat -ntlp 查看端口占用 kill -9 pid 强制杀死进程 ...
- 简单记录下@RequestBody(关于它和@RequestParam接收数据方式的拓展)
内容参考自博客:https://blog.csdn.net/ff906317011/article/details/78552426 这个标注是用来注释controller中的请求方法中的参数的,那么 ...
- 492 Construct the Rectangle 构建矩形
详见:https://leetcode.com/problems/construct-the-rectangle/description/ C++: class Solution { public: ...
- Backbone学习记录(4)
事件绑定 on()方法 调用格式:object.on(event, callback, [context])"change" — 当attributes变化时"chan ...
- 1051 - Good or Bad DFS 记忆化搜索
http://lightoj.com/volume_showproblem.php?problem=1051 对于每个位置,设dfs(cur, one, two)表示前i个字母,拥有辅音字母one个, ...
- c++ 如何对拍
首先要写好两个要对拍程序(假设是A,B),和一个制造数据的程序(设为made) (要放在同一文件夹内) 编译得到A.exe , B.exe , made.exe 写一个对拍器 格式如下 @ech ...
- 通用maper无法获取实体类com.qmtt.model.PhWxUser对应的表名问题
spring boot在采用了热加载后,可能会出现“无法获取实体类com.qmtt.model.PhWxUser对应的表名!”的异常, 解决办法 在resources新建一个文件夹META-INF,新 ...