模板·点分治(luogu P3806)
1、求树的重心
树的重心:若A点的子树中最大的子树的size[] 最小时,A为该树的中心
步骤:
- 所需变量:siz[x] 表示 x 的子树大小(含自己),msz[x] 表示 其子树中最大的子树的大小,sum表示当前子树所有节点个数,root表示当前子树根节点
- 处理出siz[x],msz[x]
- 按最大子树最小的标准处理出root
inline void GetRoot(int x,int fa){
siz[x]=1;msz[x]=0;siz[x]//表示 x 的子树大小(含自己),msz[x] 表示其子树中最大的子树的大小
for(Rint i=beg[x];i;i=nex[i]){
int y=to[i];
if(y==fa||vis[y])continue;
GetRoot(y,x);
siz[x]+=siz[y];
msz[x]=max(msz[x],siz[y]);
}
msz[x]=max(msz[x],sum-siz[x]);//按最大子树最小的标准处理出root
if(msz[x]<msz[root])root=x;
}
inline void GR_Init(int x,int fa){
sum=siz[x];//sum表示当前子树所有节点个数
root=0;//root表示当前子树根节点
GetRoot(x,fa);
}
2、分而治之
步骤:
- 处理出经过这个节点的所有所求贡献
- 减去其子树内不需要被计算但却被计算的贡献
- 对其子树继续分治
inline void Point_Divide(int x){
vis[x]=1;
Calc(x,0,1);//处理出经过这个节点的所有所求贡献
for(Rint i=beg[x];i;i=nex[i]){
int y=to[i];
if(vis[y])continue;
Calc(y,w[i],-1);//减去其子树内不需要被计算但却被计算的贡献
GR_Init(y,x);
Point_Divide(root);//对其子树继续分治
}
}
3、洛谷P3806点分治模板AC代码
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define Rint register int
#define mem(a,b) memset(a,(b),sizeof(a))
using namespace std;
typedef long long LL;
template<typename T>inline void read(T &x){
x=0;T w=1,ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
x=x*w;
}
inline void File(){
freopen("fuck.in","r",stdin);
freopen("fuck.out","w",stdout);
}
const int maxn=100000+10,inf=0x7f7f7f7f;
int n,m;
int e,beg[maxn],nex[maxn<<1],to[maxn<<1],w[maxn<<1];
int dis[maxn],siz[maxn],dep[maxn],msz[maxn];
int sum,root,cnt;
int ask[maxn],ans[maxn];
bool vis[maxn];
inline void add(int x,int y,int z){
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
w[e]=z;
}
inline void GetRoot(int x,int fa){
siz[x]=1;msz[x]=0;//siz[x]表示 x 的子树大小(含自己),msz[x] 表示其子树中最大的子树的大小
for(Rint i=beg[x];i;i=nex[i]){
int y=to[i];
if(y==fa||vis[y])continue;
GetRoot(y,x);
siz[x]+=siz[y];
msz[x]=max(msz[x],siz[y]);
}
msz[x]=max(msz[x],sum-siz[x]);//按最大子树最小的标准处理出root
if(msz[x]<msz[root])root=x;
}
inline void GR_Init(int x,int fa){
sum=siz[x];//sum表示当前子树所有节点个数
root=0;//root表示当前子树根节点
GetRoot(x,fa);
}
inline void GetDeep(int x,int fa){//处理深度
dis[++cnt]=dep[x];
for(Rint i=beg[x];i;i=nex[i]){
int y=to[i];
if(vis[y]||y==fa)continue;
dep[y]=dep[x]+w[i];
GetDeep(y,x);
}
}
inline void GD_Init(int x,int val){
cnt=0;
dep[x]=val;
GetDeep(x,0);
}
inline void Calc(int x,int val,int mrk){//计算贡献
GD_Init(x,val);
sort(dis+1,dis+cnt+1);
for(Rint i=1;i<=m;i++){
for(Rint l=1,r=cnt;l<r;l++){
while(l<r&&dis[l]+dis[r]>=ask[i]){
if(dis[l]+dis[r]==ask[i])ans[i]+=mrk;
r--;
}
}
}
}
inline void Point_Divide(int x){
vis[x]=1;
Calc(x,0,1);//处理出经过这个节点的所有所求贡献
for(Rint i=beg[x];i;i=nex[i]){
int y=to[i];
if(vis[y])continue;
Calc(y,w[i],-1);//减去其子树内不需要被计算但却被计算的贡献
GR_Init(y,x);
Point_Divide(root);//对其子树继续分治
}
}
int main(){
//File();
read(n);read(m);
for(Rint i=1;i<n;i++){
int x,y,z;read(x);read(y);read(z);
add(x,y,z);add(y,x,z);
}
for(Rint i=1;i<=m;i++)read(ask[i]);
msz[0]=inf;sum=n;GetRoot(1,0);
Point_Divide(root);
for(Rint i=1;i<=m;i++){
if(ans[i])printf("AYE\n");
else printf("NAY\n");
}
return 0;
}
模板·点分治(luogu P3806)的更多相关文章
- [luogu P3806] 【模板】点分治1
[luogu P3806] [模板]点分治1 题目背景 感谢hzwer的点分治互测. 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在. 输入输出格式 输入格式: n,m 接下来n-1条 ...
- luoguP4721 【模板】分治 FFT
P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...
- 洛谷 P4721 【模板】分治 FFT 解题报告
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...
- LG4721 【模板】分治 FFT
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 $n-1$ 的数组 $g[1],g[2],..,g[n-1]$,求 $f[0],f[1],..,f[n-1]$ ...
- Luogu P3806 点分治模板1
题意: 给定一棵有n个点的树询问树上距离为k的点对是否存在. 分析: 这个题的询问和点数都不多(但是显然暴力是不太好过的,即使有人暴力过了) 这题应该怎么用点分治呢.显然,一个模板题,我们直接用套路, ...
- [洛谷P3806] [模板] 点分治1
洛谷 P3806 传送门 这个点分治都不用减掉子树里的了,直接搞就行了. 注意第63行 if(qu[k]>=buf[j]) 不能不写,也不能写成>. 因为这个WA了半天...... 如果m ...
- Luogu 4721 【模板】分治 FFT
还不会这题的多项式求逆的算法. 发现每一项都是一个卷积的形式,那么我们可以使用$NTT$来加速,直接做是$O(n^2logn)$的,我们考虑如何加速转移. 可以采用$cdq$分治的思想,对于区间$[l ...
- [题解] Luogu P4721 【模板】分治 FFT
分治FFT的板子为什么要求逆呢 传送门 这个想法有点\(cdq\)啊,就是考虑分治,在算一段区间的时候,我们把他分成两个一样的区间,然后先做左区间的,算完过后把左区间和\(g\)卷积一下,这样就可以算 ...
- 树的点分治 板题 Luogu P3806
给定一棵有n个点的树 询问树上距离为k的点对是否存在. AC code: #include<bits/stdc++.h> using namespace std; const int MA ...
随机推荐
- CNN tricks
Must Know Tips/Tricks in Deep Neural Networks (by Xiu-Shen Wei) http://lamda.nju.edu.cn/weixs/projec ...
- Linux学习之/etc/init.d/目录和rc.local脚本
init.d目录中包含很多系统服务的启动和停止脚本,比较常用的就是网络服务,当你修改了网络配置时,可以自行 sudo /etc/init.d/networking restart 命令来重启网络服务 ...
- 面向对象基础及UML建模语言
1.面向对象的方法起源于面向对象程序设计语言,其发展过程大体经历了初始阶段.发展阶段和成熟阶段. 2.面向对象方法主要优点 (1)从认识论的角度可以看出,面向对象方法改变了开发软件的方式. (2)面向 ...
- BZOJ3524[Poi2014]Couriers——主席树
题目描述 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. 输入 第一行 ...
- (伪)再扩展中国剩余定理(洛谷P4774 [NOI2018]屠龙勇士)(中国剩余定理,扩展欧几里德,multiset)
前言 我们熟知的中国剩余定理,在使用条件上其实是很苛刻的,要求模线性方程组\(x\equiv c(\mod m)\)的模数两两互质. 于是就有了扩展中国剩余定理,其实现方法大概是通过扩展欧几里德把两个 ...
- 恕我直言,在座的各位根本写不好Java!
其实,本不想把标题写的那么恐怖,只是发现很多人干了几年 Java 以后,都自认为是一个不错的 Java 程序员了,可以拿着上万的工资都处宣扬自己了,写这篇文章的目的并不是嘲讽和我一样做 Java 的同 ...
- 【ARC102E】Stop. Otherwise...(容斥原理,动态规划)
[ARC102E]Stop. Otherwise...(容斥原理,动态规划) 题面 AtCoder 有\(n\)个骰子,每个骰子有\(K\)个面,上面有\(1\)到\(K\).骰子都是一样的. 现在对 ...
- 洛谷 P3225 [HNOI2012]矿场搭建 解题报告
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- bypy 用法
因为服务器上爬取到的40个G的数据采用http,ftp,scp传输到本地效果不太理想.找资料就看到了bypy,利用百度云存储解决这个问题,解决了服务器带宽有限的问题. pip install bypy ...
- Looper Handler Mssage
1. 一个Handler只有一个队列;2. 在调用Handler.post(Runnable runnable)方法时,会将runnable封装成一个Message;3. 在队列执行时,会判断当前的M ...