[模板]洛谷·点分治


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)的更多相关文章

  1. [luogu P3806] 【模板】点分治1

    [luogu P3806] [模板]点分治1 题目背景 感谢hzwer的点分治互测. 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在. 输入输出格式 输入格式: n,m 接下来n-1条 ...

  2. luoguP4721 【模板】分治 FFT

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

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

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

  4. LG4721 【模板】分治 FFT

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

  5. Luogu P3806 点分治模板1

    题意: 给定一棵有n个点的树询问树上距离为k的点对是否存在. 分析: 这个题的询问和点数都不多(但是显然暴力是不太好过的,即使有人暴力过了) 这题应该怎么用点分治呢.显然,一个模板题,我们直接用套路, ...

  6. [洛谷P3806] [模板] 点分治1

    洛谷 P3806 传送门 这个点分治都不用减掉子树里的了,直接搞就行了. 注意第63行 if(qu[k]>=buf[j]) 不能不写,也不能写成>. 因为这个WA了半天...... 如果m ...

  7. Luogu 4721 【模板】分治 FFT

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

  8. [题解] Luogu P4721 【模板】分治 FFT

    分治FFT的板子为什么要求逆呢 传送门 这个想法有点\(cdq\)啊,就是考虑分治,在算一段区间的时候,我们把他分成两个一样的区间,然后先做左区间的,算完过后把左区间和\(g\)卷积一下,这样就可以算 ...

  9. 树的点分治 板题 Luogu P3806

    给定一棵有n个点的树 询问树上距离为k的点对是否存在. AC code: #include<bits/stdc++.h> using namespace std; const int MA ...

随机推荐

  1. JavaScript——变量

    本文简述了JavaScript变量的数据类型,以及变量类型检测与类型转换 一.介绍 JavaScript的变量有6种数据类型,包含5种原始类型和1种对象类型.本人比较喜欢用逻辑图的形式总结知识点,这样 ...

  2. C# 之抽象类和抽象方法

    概述:abstract 关键字  抽象类不能被实例化,抽象方法不能有方法体,抽象类中的所有抽象方法必须在子类中重写(override ),一个抽象类可以同时包含抽象方法和非抽象方法. abstract ...

  3. AJAX--总结

    AJAX 2018-9-6 14:42:53 AJAX简介 ​ HTTP协议------>HTTP权威指南 ​ 请求:客户端去向服务端请求一个文件 ​ 响应:服务端把对应的文件内容返回给客户端, ...

  4. Arif in Dhaka (First Love Part 2) UVA - 10294(Polya定理)

    这题和POJ-1286一样 题意: 给出t种颜色的n颗珠子 (每种颜色的珠子个数无限制,但总数必须是n), 求能制作出项链和手镯的个数 注意手镯可以翻转和旋转  而 项练只能旋转 解析: 注意Poly ...

  5. Educational Codeforces Round 3 C. Load Balancing

    C. Load Balancing time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  6. BAI度 内部资料!Python_Threads多线程

    基本介绍 runable运行sleeping等待dead销毁(run方法执行完成或执行时抛出异常) 类继承threading.Thread线程的状态 函数介绍 在__init__里调用threadin ...

  7. 【BZOJ4503】两个串(FFT)

    [BZOJ4503]两个串(FFT) 题面 给定串\(S\),以及带通配符的串\(T\),询问\(T\)在\(S\)中出现了几次.并且输出对应的位置. \(|S|,|T|<=10^5\),字符集 ...

  8. LoadRunner回放乱码

    乱码的原因和服务器字符集编码相关,默认LR是gbk解码,如果服务器是utf8,那么需要改为utf8解码,这样中文就显示正常了. 通过查看源码,可以知道服务器的编码方式:<meta charset ...

  9. luogu3385 负环 (spfa)

    我在做spfa的时候,如果有一个点被更新了超过N次,证明这个图里是有负环的. (神TM输出YE5和N0) #include<bits/stdc++.h> #define pa pair&l ...

  10. 【uoj207】 共价大爷游长沙

    http://uoj.ac/problem/207 (题目链接) 题意 给出一棵无根树,4种操作:在路径集合中加入一条路径,在路径集合中删除一条路径,删一条边加一条边,查询一条边是否被集合中所有路径经 ...