BZOJ.1468.Tree(点分治)
题意: 计算树上距离<=K的点对数
我们知道树上一条路径要么经过根节点,要么在同一棵子树中。
于是对一个点x我们可以这样统计: 计算出所有点到它的距离dep[],排序后可以O(n)求得<=K的点对数量。
但画个图后我们可以发现,对于在同一棵子树中的路径被重复计算过了。于是我们Ans-=Calc(v),减去一棵子树中的路径答案,但是这并不是之前x到它们的路径,于是给v的dep[]设一个初始值为w(x->v路径权值)。
这样x的答案就计算完了,将这一过程记作Solve(x)。
考虑如何计算所有点。DFS的效率是和树深有关的。计算x->v时,我们选取v子树上的重心作为下次Solve()的参数。
选取重心每次都会使树的节点个数减半,因此递归深度最坏(链)是logn的。
这样便可O(nlog^2n)解决该题。
//2524kb 656ms
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=40005,MAXIN=1e5;
int n,K,root,Min,Ans,Enum,H[N],nxt[N<<1],to[N<<1],val[N<<1],dep[N],sz[N],D[N];
bool vis[N];
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v,int w)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, val[Enum]=w;
}
void Get_Root(int x,int f,int tot)
{
int mx=0; sz[x]=1;
for(int v,i=H[x]; i; i=nxt[i])
if(!vis[to[i]] && to[i]!=f)
{
Get_Root(v=to[i],x,tot), sz[x]+=sz[v];
if(sz[v]>mx) mx=sz[v];
}
mx=std::max(mx,tot-sz[x]);
if(mx<Min) Min=mx, root=x;
}
void DFS(int x,int f)
{
D[++D[0]]=dep[x];
for(int i=H[x]; i; i=nxt[i])
if(!vis[to[i]]&&to[i]!=f)
dep[to[i]]=dep[x]+val[i], DFS(to[i],x);
}
int Calc(int x,int v)
{
D[0]=0, dep[x]=v, DFS(x,-1);
std::sort(D+1,D+1+D[0]);
int l=1,r=D[0],res=0;
while(l<r)
if(D[l]+D[r]<=K) res+=r-l,++l;
else --r;
return res;
}
void Solve(int x)
{
Ans+=Calc(x,0), vis[x]=1;
for(int v,i=H[x]; i; i=nxt[i])
if(!vis[to[i]])
{
Ans-=Calc(v=to[i],val[i]);
Min=N, Get_Root(v,x,sz[v]), Solve(root);
}
}
int main()
{
n=read();
for(int u,v,w,i=1; i<n; ++i) u=read(),v=read(),w=read(),AddEdge(u,v,w);
K=read();
Min=N, Get_Root(1,-1,n), Solve(root);
printf("%d",Ans);
return 0;
}
BZOJ.1468.Tree(点分治)的更多相关文章
- bzoj 1468 Tree(点分治模板)
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1527 Solved: 818[Submit][Status][Discuss] ...
- BZOJ 1468 Tree 【模板】树上点分治
#include<cstdio> #include<algorithm> #define N 50010 #define M 500010 #define rg registe ...
- BZOJ 1468: Tree
Description 真·树,问距离不大于 \(k\) 的点对个数. Sol 点分治. 同上. Code /********************************************* ...
- 【刷题】BZOJ 1468 Tree
Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是 ...
- bzoj 1468 Tree 点分
Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1972 Solved: 1101[Submit][Status][Discuss] Desc ...
- 【BZOJ-1468】Tree 树分治
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1025 Solved: 534[Submit][Status][Discuss] ...
- bzoj 2212 Tree Rotations
bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...
- [BZOJ 3456]城市规划(cdq分治+FFT)
[BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...
- [BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)
[BZOJ 2989]数列(CDQ 分治) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...
随机推荐
- 【转】Visual Studio——多字节编码与Unicode码
多字节字符与宽字节字符 1) char与wchar_t 我们知道C++基本数据类型中表示字符的有两种:char.wchar_t. char叫多字节字符,一个char占一个字节,之所以叫多字节字符是因为 ...
- js 、c# 编码解码
escape不编码字符有69个:*,+,-,.,/,@,_,0-9,a-z,A-Z encodeURI不编码字符有82个:!,#,$,&,',(,),*,+,,,-,.,/,:,;,=,?,@ ...
- (常用)re模块
re模块(正则)#re:一些带有特殊含义的符号或者符号的组合#为什么要用re:一堆字符串中找到你所需要的内容,过滤规则是什么样,通过re模块功能来告诉计算机你的过滤规则#应用:在爬虫中最为常用:使用爬 ...
- PHP获取网卡的MAC地址原码;目前支持WIN/LINUX系统 获取机器网卡的物理(MAC)地址
声明转换于其它博客当中的. <?php /** 获取网卡的MAC地址原码:目前支持WIN/LINUX系统 获取机器网卡的物理(MAC)地址 **/ class GetMacAddr{ var $ ...
- Python-JS基础(基础结构~函数)
程序本质上分为三大结构: 顺序结构.分支结构.循环结构JavaScript中的程序结构也是这样,下面我们来分别介绍JS中的三种基本程序结构:我们上篇博客中介绍到的使用逻辑运算符&&实现 ...
- SpringMVC(1):Web MVC简介
原文出处: 张开涛 Web MVC简介 1.1.Web开发中的请求-响应模型: 在Web世界里,具体步骤如下: 1. Web浏览器(如IE)发起请求,如访问 2. Web服务器(如Tomcat)接 ...
- node path.resolve()
作用: path.resolve()方法将一系列路径或路径段解析为绝对路径. 语法: path.resolve([from ...], to) 说明:将参数 to 位置的字符解析到一个绝对路径里. 参 ...
- Redis Windows上下载安装
其它的默认就可. public class RedisTest { public static void main(String[] args) { Jedis jedis = RedisPool.g ...
- bootstrap----屏幕大小切换
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ural1855 线段树区间更新+推公式维护一元二次式
和威威猫系列故事差不多,都是根据条件推出公式 /* 操作c a b d:a到b道路上的所有边权值加d 操作e a b:问a到b中包含的道路的平均权值 区间平均值=所有可能路径权值/所有路径数, 而路径 ...