【BZOJ】1468: Tree(点分治)
http://www.lydsy.com/JudgeOnline/problem.php?id=1468
分治真是一门高大上的东西。。。
好神。。。
树分治最好资料是:qzc的《分治算法在树的路径问题中的应用》
我来说说自己的理解:
点分=找重心+分治
找重心尤为重要,因为这关系到时间复杂度。
对于递归式
$$T(n)=aT(n/b)+O(D(n))$$
这类递归式,如果能保证每一层都是$O(D(n))$,那么时间复杂度会大大减小。(详见算导第三章和第四章)
对于一棵树,如果我们在找到重心后,用线性做法处理完当前层,那么就可以log级别处理完整棵树,比如:
递归式
$$T(n)=aT(n/a)+O(n)$$
就是非常一般的点分的分治,在这里复杂度为$O(nlog_{a}n)$,具体证明看算导。。(很简单的。。。。。
然而在树分治中,最多递归log次(因为是找了重心),因此复杂度降到$O(nlgn)$
因此如果我们能线性时间内处理好每一层,问题就能在nlgn的时间内得以解决。。。。。
本题裸的路径询问。。。。。。。。。。。。。。。。。。。。。。。。。。。对于此类问题,考虑经过每个点的路径。。。。
预处理当前根所有子树的信息,然后加上根然后合并就能得到一条经过根的路径!然后就行了。。。。。随便搞搞就能线性了。。
本题只要将当前根所有子树节点到根的距离全部跑出来,排序后因为单调维护一下即可。。。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } const int N=40005, oo=~0u>>1;
int ihead[N], cnt, K;
struct dat { int next, to, w; }e[N<<1];
void add(int u, int v, int w) {
e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].w=w;
e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].w=w;
} int dep[N], d[N], cdep, ans, mn;
int root, sz[N], vis[N];
void getroot(int x, int fa, int sum) {
sz[x]=1; int y, mx=0;
rdm(x, i) if(!vis[y=e[i].to] && e[i].to!=fa) {
getroot(y, x, sum);
sz[x]+=sz[y];
mx=max(mx, sz[y]);
}
mx=max(mx, sum-mx);
if(mx<mn) mn=mx, root=x;
}
void getdep(int x, int fa) {
dep[++cdep]=d[x]; int y; //printf("x:%d\tfa:%d\tdep:%d\n", x, fa, dep[x]);
rdm(x, i) if(!vis[y=e[i].to] && e[i].to!=fa) {
d[y]=d[x]+e[i].w;
getdep(y, x);
}
}
int cal(int x, int last=0) {
cdep=0; d[x]=last; //printf("root is:%d\n", x);
getdep(x, -1); //puts("==========================");
int ret=0, front=1, tail=cdep;
sort(dep+1, dep+1+cdep);
while(front<tail) {
while(front<tail && dep[tail]+dep[front]>K) --tail;
ret+=tail-front;
++front;
}
return ret;
}
void dfs(int x, int all) {
vis[x]=1; int y;
ans+=cal(x); //printf("root:%d\n", x);
rdm(x, i) if(!vis[y=e[i].to]) {
ans-=cal(y, e[i].w);
int s=sz[y]>sz[x]?all-sz[x]:sz[y];
root=0; mn=oo; getroot(y, x, s);
dfs(root, s);
}
} int main() {
int n=getint();
rep(i, n-1) { int u=getint(), v=getint(), w=getint(); add(u, v, w); }
read(K); mn=oo;
getroot((n+1)>>1, -1, n);
dfs(root, n);
printf("%d\n", ans);
return 0;
}
Description
Input
Output
Sample Input
1 6 13
6 3 9
3 5 7
4 1 3
2 4 20
4 7 2
10
Sample Output
HINT
Source
【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(点分治)
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 ...
- 【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]| ...
随机推荐
- jquery.fileupload.js 杂记
通过$your_jq_dom.fileupload({},donf:function...,fail:function..., ...) 得到的只是一个支持上传的控件,当然绑定了各种事件. 传参给ur ...
- MySQL使用索引的场景及真正利用索引的SQL类型
1. 为什么使用索引 在无索引的情况下,MySQL会扫描整张表来查找符合sql条件的记录,其时间开销与表中数据量呈正相关.对关系型数据表中的某些字段建索引可以极大提高查询速度(当然,不同字段是否sel ...
- 查看Eclipse中的jar包的源代码:jd-gui.exe
前面搞了很久的使用JAD,各种下载插件,最后配置好了,还是不能用,不知道怎么回事, 想起一起用过的jd-gui.exe这个工具,是各种强大啊!!! 只需要把jar包直接扔进去就可以了,非常清晰,全部解 ...
- Android clickable 和 focusable
setClickable(),好像是控制按钮是否可以被点击和点击之后触发监听器事件.setFocusable();控制键盘是否可以获得这个按钮的焦点.(我按实体键盘上方向键,button被选中) 今天 ...
- sphinx 增量索引与主索引使用测试
2013年10月28日 15:01:16 首先对新增的商品建立增量索引,搜索时只使用增量索引: array (size=1) 0 => array (size=6) 'gid' => st ...
- Java for LeetCode 165 Compare Version Numbers
Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 &l ...
- 新建myeclipse工作空间需要的工作
接触了许多个项目,都挺大的,每次都需要配置,简单总结总结. 第一.右击项目,选择Text file encoding 第二.点击window-->preferences-->myeclip ...
- c++ 继承 虚函数与多态性 重载 覆盖 隐藏
http://blog.csdn.net/lushujun2011/article/details/6827555 2011.9.27 1) 定义一个对象时,就调用了构造函数.如果一个类中没有定义任何 ...
- charles使用教程指南(抓包工具)
0x01 前言: Charles是一款抓包修改工具,相比起burp,charles具有界面简单直观,易于上手,数据请求控制容易,修改简单,抓取数据的开始暂停方便等等优势!下面来详细介绍下这款强大好用的 ...
- 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))
解决办法:在项目属性里设置“生成”=>“目标平台”为x86而不是默认的ANY CPU.