【题意】给定带边权树,求两点距离<=k的点对数。n<=40000。

【算法】点分治

【题解】对于一个区域,选择其重心x作为根,则划分出来的每棵子树都是子区域,可以证明至多划分log n次(通过vis[]划分区域)。每次划分所有点都扫描一次,所以仅遍历的复杂度是O(n log n)。

对于本题,将点x的所有子树节点dis处理出来后排序,然后用双指针法易得<=k的点对数。

但是,这样会把来自同一子树的路径也计算进去,需要减去。来自同一子树y的距离<=k的路径的数量等同于子树y内路径的距离+2*w<=k的路径的数量。

所以,设dis[y]=w后再减去子树y的路径数即可。

具体做法:calc(x,0)表示dis[x]=0统计得到的子树x内<=k的路径数,则ans(x)=calc(x,0)-calc(y,w),y=son[x],w是边(x,y)的权值。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=;
ll ans;
int root,first[maxn],tot,cnt,sz[maxn],sum,d[maxn],k,n;
bool vis[maxn];
struct edge{int v,w,from;}e[maxn*];
void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
void getroot(int x,int fa){
sz[x]=;
bool ok=;
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v]){
getroot(e[i].v,x);
sz[x]+=sz[e[i].v];
if(sz[e[i].v]>sum/)ok=;
}
if(sum-sz[x]<=sum/&&ok)root=x;
}
void getdeep(int x,int fa,int w){
d[++cnt]=w;
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v])getdeep(e[i].v,x,w+e[i].w);
}
ll calc(int x,int w){
cnt=;getdeep(x,,w);
sort(d+,d+cnt+);
int l=,r=cnt;
ll sum=;
while(l<r){
if(d[l]+d[r]<=k){sum+=r-l;l++;}
else r--;
}
return sum;
}
void solve(int x,int s){
ans+=calc(x,);vis[x]=;
for(int i=first[x];i;i=e[i].from)if(!vis[e[i].v]){
ans-=calc(e[i].v,e[i].w);
if(sz[e[i].v]>sz[x])sum=s-sz[x];else sum=sz[e[i].v];
getroot(e[i].v,x);
solve(root,sum);
}
}
int main(){
scanf("%d",&n);
int u,v,w;
for(int i=;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);insert(v,u,w);
}
scanf("%d",&k);
sum=n;
getroot(,);
ans=;
solve(root,n);
printf("%lld\n",ans);
return ;
}

【BZOJ】1468: Tree(POJ1741) 点分治的更多相关文章

  1. bzoj 1468 Tree(点分治模板)

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1527  Solved: 818[Submit][Status][Discuss] ...

  2. 【BZOJ】1468: Tree(点分治)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1468 分治真是一门高大上的东西... 好神... 树分治最好资料是:qzc的<分治算法在树的路 ...

  3. BZOJ.1468.Tree(点分治)

    BZOJ1468 POJ1741 题意: 计算树上距离<=K的点对数 我们知道树上一条路径要么经过根节点,要么在同一棵子树中. 于是对一个点x我们可以这样统计: 计算出所有点到它的距离dep[] ...

  4. BZOJ 1468 Tree 【模板】树上点分治

    #include<cstdio> #include<algorithm> #define N 50010 #define M 500010 #define rg registe ...

  5. BZOJ 1468: Tree

    Description 真·树,问距离不大于 \(k\) 的点对个数. Sol 点分治. 同上. Code /********************************************* ...

  6. 【刷题】BZOJ 1468 Tree

    Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是 ...

  7. bzoj 1468 Tree 点分

    Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1972  Solved: 1101[Submit][Status][Discuss] Desc ...

  8. 【POJ1741】Tree(点分治)

    [POJ1741]Tree(点分治) 题面 Vjudge 题目大意: 求树中距离小于\(K\)的点对的数量 题解 完全不觉得点分治了.. 简直\(GG\),更别说动态点分治了... 于是来复习一下. ...

  9. hdu 4670 Cube number on a tree(点分治)

    Cube number on a tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/ ...

  10. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

随机推荐

  1. 常用的比较器:实现方式Compareable和Comparator

    class Dog{ int size; int weight; public Dog(int s, int w){ size = s; weight = w; } } 目的:对于Dog对象作为元素所 ...

  2. Node.js系列——(3)连接DB

    背景 node.js,有人称之为运行在服务器端的JavaScript.以往我们使用JavaScript时,都是依赖后端查询数据库并返回数据,而JavaScript只需要展示即可.问题来了,就不能绕开后 ...

  3. TP中if标签

    if标签 If标签如果php中if语句的作用,if是用于流程控制的. 在ThinkPHP中if标签也是用于流程控制的. If标签的语法格式: <if condition=’条件表达式’> ...

  4. MySQL专题3 SQL 优化

    这两天去京东面试,面试官问了我一个问题,如何优化SQL 我上网查了一下资料,找到了不少方法,做一下记录 (一). 首先使用慢查询分析  通过Mysql 的Slow Query log 可以找到哪些SQ ...

  5. 第149天:javascript中this的指向详解

    js中的this指向十分重要,了解js中this指向是每一个学习js的人必学的知识点,今天没事,正好总结了js中this的常见用法,喜欢的可以看看: 1.全局作用域或者普通函数中this指向全局对象w ...

  6. Spring Cloud Sleuth服务跟踪

    监控 使用zipkin(https://zipkin.io/) 监控服务构建: (普通的springBoot项目) <!--引入的zipkinServer依赖--> <depende ...

  7. hadoop跑第一个实例过程

    第一次跑hadoop实例,中间经过了不少弯路,特此记录下来: 第一步:建立一个maven过程,pom.xml文件:(打包为jar包) <dependency> <groupId> ...

  8. bzoj5123 [Lydsy12月赛]线段树的匹配

    题意: 线段树是这样一种数据结构:根节点表示区间 [1, n]:对于任意一个表示区间 [l, r] 的节点,若 l < r, 则取 mid = ⌊l+r/2⌋,该节点的左儿子为 [l, mid] ...

  9. [Code Festival 2017 qual A] C: Palindromic Matrix

    题意 给出一个小写字母组成的字符矩阵,问能否通过重排其中的字符使得每行每列都是回文串. 分析 简化版:给出一个字符串,问能否通过重排其中的字符使得它是回文串.那么如果字符串长度为偶数,就需要a到z的个 ...

  10. 【uoj#174】新年的破栈 贪心

    题目描述 给你一个长度为 $n$ 的序列和一个空的双端队列,每次进行3种操作种的一种: 1.将序列中编号最小的数加入到双端队列的队尾:2.从双端队列的队尾取出一个数:3.从双端队列的队头取出一个数. ...