【BZOJ】1468: Tree(POJ1741) 点分治
【题意】给定带边权树,求两点距离<=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) 点分治的更多相关文章
- bzoj 1468 Tree(点分治模板)
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1527 Solved: 818[Submit][Status][Discuss] ...
- 【BZOJ】1468: Tree(点分治)
http://www.lydsy.com/JudgeOnline/problem.php?id=1468 分治真是一门高大上的东西... 好神... 树分治最好资料是:qzc的<分治算法在树的路 ...
- BZOJ.1468.Tree(点分治)
BZOJ1468 POJ1741 题意: 计算树上距离<=K的点对数 我们知道树上一条路径要么经过根节点,要么在同一棵子树中. 于是对一个点x我们可以这样统计: 计算出所有点到它的距离dep[] ...
- 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 ...
- 【POJ1741】Tree(点分治)
[POJ1741]Tree(点分治) 题面 Vjudge 题目大意: 求树中距离小于\(K\)的点对的数量 题解 完全不觉得点分治了.. 简直\(GG\),更别说动态点分治了... 于是来复习一下. ...
- 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/ ...
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
随机推荐
- 老司机带你解读jQuery插件开发流程
jquery插件开发模式 jquery插件一般有三种开发方式: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget()应用jQuery UI的部 ...
- lintcode-81-数据流中位数
81-数据流中位数 数字是不断进入数组的,在每次添加一个新的数进入数组的同时返回当前新数组的中位数. 说明 中位数的定义: 中位数是排序后数组的中间值,如果有数组中有n个数,则中位数为A[(n-1)/ ...
- Objective - C 之协议
一.创建方法: 二.实现过程: 1.遵循协议: @protocol NurseWorkingProtocol <NSObject> //<> 表示遵守协议,创建时就有(Nu ...
- gridview 第一行编辑
<%@ Page Language="C#" AutoEventWireup="true" Codebehind="Default.aspx.c ...
- codeforces 1027 E. Inverse coloring (DP)
E. Inverse Coloring time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- bzoj3517 翻硬币
题意 有一个n行n列的棋盘,每个格子上都有一个硬币,且n为偶数.每个硬币要么是正面朝上,要么是反面朝上.每次操作你可以选定一个格子(x,y),然后将第x行和第y列的所有硬币都翻面.求将所有硬币都变成同 ...
- Android四大组件之Intent(续2)
1.你如何通过一个intent来唤醒activity? this.startActivity(intent,request); 2.什么是显式.隐式的intents? 显式:指定组件名,通常 ...
- C++解析(3):布尔类型与三目运算符
0.目录 1.布尔类型 2.三目运算符 3.小结 1.布尔类型 C++中的布尔类型: C++在C语言的基本类型系统之上增加了bool C++中的bool可取的值只有true和false 理论上bool ...
- 【刷题】BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡
Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...
- 【刷题】BZOJ 4196 [Noi2015]软件包管理器
Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...