luogu 3806 【模板】点分治

给定一棵有n个点的树,有m个询问,每个询问树上距离为k的点对是否存在。树的权值最多不超过c。n<=10000,m<=100,c<=1000,K<=10000000。

关于树的路径的问题,点分治是一种最吼的工具。由于这道题的m比较小,枚举k,通过set保存每颗子树中点的路径值,在set中查询每个k值是否成立即可。似乎空间消耗很小,只用了2.3mb。

#include <set>
#include <cctype>
#include <cstdio>
#include <cstring>
using namespace std; const int maxn=1e4+5; struct Graph{
struct Edge{
int to, next, v; Graph *bel;
Edge& operator ++(){
return *this=bel->edge[next]; }
}edge[maxn*2];
int cnte, fir[maxn];
void addedge(int x, int y, int v){
Edge &e=edge[++cnte];
e.to=y; e.next=fir[x]; e.v=v;
fir[x]=cnte; e.bel=this;
}
Edge& getlink(int x){ return edge[fir[x]]; }
void RESET(){
cnte=0; memset(fir, 0, sizeof(fir)); }
}g; int n, m, k[maxn], size[maxn], f[maxn];
int dep[maxn], tail;
set<int> s;
bool done[maxn], hasans[maxn]; //获取子树大小和最大子树大小
void predfs(int now, int par, int num){
Graph::Edge e=g.getlink(now);
size[now]=1; f[now]=0;
for (; e.to; ++e){
if (e.to==par||done[e.to]) continue;
predfs(e.to, now, num);
size[now]+=size[e.to];
f[now]=max(f[now], size[e.to]);
}
f[now]=max(f[now], num-size[now]);
} //找到根
int getroot(int now, int par){
Graph::Edge e=g.getlink(now);
int core=now, t;
for (; e.to; ++e){
if (e.to==par||done[e.to]) continue;
t=getroot(e.to, now);
if (f[t]<f[core]) core=t;
}
return core;
} //获取到所有点的深度
void getdep(int now, int par, int step){
Graph::Edge e=g.getlink(now);
for (; e.to; ++e) if (e.to!=par&&!done[e.to])
getdep(e.to, now, step+e.v);
dep[++tail]=step;
for (int i=1; i<=m; ++i)
if (s.find(k[i]-dep[tail])!=s.end())
hasans[i]=true;
} void solve(int now, int par, int num){
predfs(now, 0, num); //预处理
if (size[now]==1) return;
now=getroot(now, 0); //找出重心
predfs(now, 0, num);
s.clear(); s.insert(0);
Graph::Edge e=g.getlink(now);
for (; e.to; ++e){
if (e.to==par||done[e.to]) continue;
tail=0;
getdep(e.to, now, e.v); //找出所有点的深度
for (int i=1; i<=tail; ++i)
s.insert(dep[i]);
}
//不能统计带有回头路的
e=g.getlink(now);
done[now]=true;
for (; e.to; ++e) if (e.to!=par&&!done[e.to])
solve(e.to, now, size[e.to]); //找子树
} void get(int &x){
x=0; int flag=1; char c;
for (c=getchar(); !isdigit(c); c=getchar())
if (c=='-') flag=-flag;
for (x=c-48; c=getchar(), isdigit(c); )
x=(x<<3)+(x<<1)+c-48; x*=flag;
} int main(){
get(n); get(m);
int t1, t2, t3;
for (int i=1; i<n; ++i){
get(t1); get(t2); get(t3);
g.addedge(t1, t2, t3);
g.addedge(t2, t1, t3);
}
for (int i=1; i<=m; ++i) get(k[i]);
solve(1, 0, n);
for (int i=1; i<=m; ++i) puts(hasans[i]?"AYE":"NAY");
return 0;
}

luogu 3806 【模板】点分治的更多相关文章

  1. Luogu 3806 点分治1

    Luogu 3806 点分治 要分清楚各个函数的作用及互相调用的关系. 因为是无根树,找重心的时候,父亲一边的所有节点也可以看做是一颗子树. #include<bits/stdc++.h> ...

  2. luoguP4721 【模板】分治 FFT

    P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...

  3. [luogu P3384] [模板]树链剖分

    [luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...

  4. 洛谷 P4721 【模板】分治 FFT 解题报告

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...

  5. Luogu P2742 模板-二维凸包

    Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...

  6. LG4721 【模板】分治 FFT

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 $n-1$ 的数组 $g[1],g[2],..,g[n-1]$,求 $f[0],f[1],..,f[n-1]$ ...

  7. luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

    luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...

  8. 模板·点分治(luogu P3806)

    [模板]洛谷·点分治 1.求树的重心 树的重心:若A点的子树中最大的子树的size[] 最小时,A为该树的中心 步骤: 所需变量:siz[x] 表示 x 的子树大小(含自己),msz[x] 表示 其子 ...

  9. Luogu 4721 【模板】分治 FFT

    还不会这题的多项式求逆的算法. 发现每一项都是一个卷积的形式,那么我们可以使用$NTT$来加速,直接做是$O(n^2logn)$的,我们考虑如何加速转移. 可以采用$cdq$分治的思想,对于区间$[l ...

随机推荐

  1. DBGrid1

    A.ShowMessage(IntToStr(Column.Index));   B.ShowMessage(IntToStr(dbgrid1.SelectedField.Index)); .得到当前 ...

  2. python-socket2

    UDP,服务端 #! /usr/bin/env python #coding=utf-8 import socket #创建socket,指定ipv4,udp类型 s = socket.socket( ...

  3. pyglet模块的EventDispatcher(事件派发对象)

    事件派发对象用于处理事件的派发与响应,pyglet的window对象正是继承了它才具有处理事件的能力. 步骤: 1.注册事件类型: EventDispatcher.register_event_typ ...

  4. leetcode 204. Count Primes(线性筛素数)

    Description: Count the number of prime numbers less than a non-negative number, n. 题解:就是线性筛素数的模板题. c ...

  5. 【遍历二叉树】02二叉树的中序遍历【Binary Tree Inorder Traversal】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,返回他的中序遍历的 ...

  6. sws_scale函数的用法-具体应用

    移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章.文章虽然已经过去很长时间,但是还有颇多可以借鉴之处.谢谢“咕咕鐘". 转自:http://guguclock.blog ...

  7. P1364 医院设置

    题目描述 设有一棵二叉树,如图: 其中,圈中的数字表示结点中居民的人口.圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为l.如上 ...

  8. CentOS配置LDAP服务器

    环境:centos 5.8 安装: 1.yum安装oepnldap.openldap-servers.openldap-clients.openldap-devel [root@hao-linux ~ ...

  9. ffmpeg+HLS实现直播与回放

    Nginx配置视频服务器 server { listen ; server_name localhost; location /hls{ add_header Access-Control-Allow ...

  10. Struts2学习第七课 OGNL

    request变成了struts重写的StrutsRequestWrapper 关于值栈: helloWorld时,${productName}读取productName值,实际上该属性并不在requ ...