【BZOJ 1468】Tree 点分治

点分治$O(nlogn)$

坚持到月考结束后新校就剩下我一个OIer,其他人早已停课了,老师估计懒得为我一个人开机房门,让我跟班主任说了一声,今晚就回到了老校,开始了自己都没有想到会来的这么早的停课生活。

所以先水一道点分治

#include<cstdio>
#include<algorithm>
#define read(x) x=getint()
#define N 40003
#define max(a,b) (a)>(b)?(a):(b)
using namespace std;
inline int getint() {
	char c; int fh=1, k=0;
	for( ; c < ‘0‘ || c > ‘9‘; c=getchar()) if ( c == ‘-‘) fh = -1;
	for( ; c >= ‘0‘ && c <= ‘9‘; c=getchar()) k = k * 10 + c - ‘0‘;
	return k * fh;
}
struct node {
	int nxt, to, w;
} E[N << 1];
bool vis[N];
int root, rtm = N, n, K, cnt = 0, sz[N], di[N], tb[N], tn, ans = 0, point[N];
inline void ins( int x, int y, int z) {cnt++; E[cnt].nxt = point[x]; E[cnt].to = y; E[cnt].w = z; point[x] = cnt;}
inline void fdrt( int x, int fa, int s) {
	sz[x] = 1;
	int ma=0;
	for( int tmp = point[x]; tmp; tmp = E[tmp].nxt)
		if ( !vis[E[tmp].to] && E[tmp].to != fa) {
			fdrt( E[tmp].to, x, s);
			sz[x] += sz[E[tmp].to];
			ma = max( ma, sz[E[tmp].to]);
		}
	ma = max( ma, s - ma);
	if ( ma < rtm) {
		rtm = ma;
		root = x;
	}
}
inline void mktb( int x, int fa) {
	tb[++tn] = di[x];
	for( int tmp = point[x]; tmp; tmp = E[tmp].nxt)
		if ( !vis[E[tmp].to] && E[tmp].to != fa) {
			di[E[tmp].to] = di[x] + E[tmp].w;
			mktb( E[tmp].to, x);
		}
}
inline int work( int x, int la) {
	di[x] = la;
	tn = 0;
	mktb( x, -1);
	sort( tb + 1, tb + tn + 1);
	int head = 1, tail = tn, an = 0;
	while ( head < tail) {
		while ( head < tail && tb[head] + tb[tail] > K)
			--tail;
		an += tail - head;
		++head;
	}
	return an;
}
inline void dfs( int x, int s) {
	vis[x] = 1;
	ans += work( x, 0);
	for( int tmp = point[x]; tmp; tmp = E[tmp].nxt)
		if ( !vis[E[tmp].to]) {
			ans -= work( E[tmp].to, E[tmp].w);
			rtm = N;
			int ss = sz[x] > sz[E[tmp].to] ? sz[E[tmp].to] : s - sz[x];
			fdrt( E[tmp].to, x, ss);
			dfs( root, ss);
		}
}
int main() {
	read(n);
	int u, v, e;
	for( int i = 1; i < n; ++i) {
		read(u); read(v); read(e);
		ins( u, v, e);
		ins( v, u, e);
	}
	read(K);
	fdrt( 1, -1, n);
	dfs( root, n);
	printf( "%d\n", ans);
	return 0;
}

第一次交我忘了sort了,,,

时间: 03-25

【BZOJ 1468】Tree 点分治的相关文章

bzoj 1468 Tree(点分治模板)

1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1527  Solved: 818[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k Output 一行,有多少对点之间的距离小于等于k Sample Input 7 1 6 13 6

BZOJ.1468.Tree(点分治)

题目链接 BZOJ1468 POJ1741 题意: 计算树上距离<=K的点对数 我们知道树上一条路径要么经过根节点,要么在同一棵子树中. 于是对一个点x我们可以这样统计: 计算出所有点到它的距离dep[],排序后可以O(n)求得<=K的点对数量. 但画个图后我们可以发现,对于在同一棵子树中的路径被重复计算过了.于是我们Ans-=Calc(v),减去一棵子树中的路径答案,但是这并不是之前x到它们的路径,于是给v的dep[]设一个初始值为w(x->v路径权值). 这样x的答案就计算完了,将这

[bzoj 1468] Tree

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1468 Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1517  Solved: 812[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

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

1 #include<cstdio> 2 #include<algorithm> 3 #define N 50010 4 #define M 500010 5 #define rg register 6 #define LL long long 7 using namespace std; 8 int n,m,cnt,root,tot,totnow,totbf; 9 int last[N],size[N],mxsize[N],dep[N],tmp[N],mg[N]; 10 LL a

点分治专题——bzoj 1468 &amp;bzoj 2152 题解

[前言]最近一直在忙着学算法,但是效果似乎不是很好.前段时间的树剖也快忘了= =.树套树没熟练,就开始写主席树了= =.更别说本身就不是很懂的莫比乌斯反演了.~~决定好好复习一下. [点分治的作用]套用SYC大神的话说是:用来解决树上路径点权统计问题. [大致流程] ①找出这颗树的重心. ②统计经过这个重心的答案 ③用重心把树割开 ④对每个"小树"做同样的事 [Q1--重心]其实找重心再进行计算只是为了不被卡链.什么是重心?就是当前树中的一个点K,使得MAX(SON[K])最小.SON

【BZOJ-1468】Tree 树分治

1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k Output 一行,有多少对点之间的距离小于等于k Sample Input 7 1 6 13 6

[LeetCode] Convert Sorted List to Binary Search Tree(分治)

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. 方法:为了使BST高度平衡,要找链表中的中值作为当前根节点. /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) :

【BZOJ】1468: Tree(点分治)

http://www.lydsy.com/JudgeOnline/problem.php?id=1468 分治真是一门高大上的东西... 好神... 树分治最好资料是:qzc的<分治算法在树的路径问题中的应用> 我来说说自己的理解: 点分=找重心+分治 找重心尤为重要,因为这关系到时间复杂度. 对于递归式 $$T(n)=aT(n/b)+O(D(n))$$ 这类递归式,如果能保证每一层都是$O(D(n))$,那么时间复杂度会大大减小.(详见算导第三章和第四章) 对于一棵树,如果我们在找到重心后,

1468. Tree【点分治】

Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k Output 一行,有多少对点之间的距离小于等于k Sample Input 7 1 6 13 6 3 9 3 5 7 4 1 3 2 4 20 4 7 2 10 Sample Output 5 点分治模板 1 #include<iostream> 2 #include<cstring&