【BZOJ2051】A Problem For Fun

【题目链接】

【三倍经验链接】

【思路要点】

  • 二分答案,在点分树内查询小于答案的路径条数。
  • 时间复杂度\(O(NLog^3N)\)。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	100005
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
vector <int> dest[MAXN], len[MAXN], a[MAXN];
vector <int> vroot[MAXN], vson[MAXN];
map <int, int> mp[MAXN];
int n, k, root, cntpoints;
int size[MAXN], weight[MAXN];
int father[MAXN];
bool visited[MAXN];
void chkmax(int &x, int y) {
	x = max(x, y);
}
void getroot(int pos, int fa) {
	size[pos] = 1;
	weight[pos] = 0;
	for (unsigned i = 0; i < dest[pos].size(); i++) {
		if (dest[pos][i] == fa || visited[dest[pos][i]]) continue;
		getroot(dest[pos][i], pos);
		size[pos] += size[dest[pos][i]];
		chkmax(weight[pos], size[dest[pos][i]]);
	}
	chkmax(weight[pos], cntpoints - size[pos]);
	if (weight[pos] < weight[root]) root = pos;
}
void calsize(int pos, int fa) {
	size[pos] = 1;
	for (unsigned i = 0; i < dest[pos].size(); i++) {
		if (dest[pos][i] == fa || visited[dest[pos][i]]) continue;
		calsize(dest[pos][i], pos);
		size[pos] += size[dest[pos][i]];
	}
}
void getvroot(int root, int pos, int fa, int dist) {
	vroot[root].push_back(dist);
	mp[root][pos] = dist;
	for (unsigned i = 0; i < dest[pos].size(); i++) {
		if (visited[dest[pos][i]] || dest[pos][i] == fa) continue;
		getvroot(root, dest[pos][i], pos, dist + len[pos][i]);
	}
}
void getvson(int root, int pos, int fa, int dist) {
	vson[root].push_back(dist);
	for (unsigned i = 0; i < dest[pos].size(); i++) {
		if (visited[dest[pos][i]] || dest[pos][i] == fa) continue;
		getvson(root, dest[pos][i], pos, dist + len[pos][i]);
	}
}
void work(int pos) {
	visited[pos] = true;
	calsize(pos, 0);
	getvroot(pos, pos, 0, 0);
	for (unsigned i = 0; i < dest[pos].size(); i++) {
		if (visited[dest[pos][i]]) continue;
		root = 0; cntpoints = size[dest[pos][i]];
		getroot(dest[pos][i], pos);
		a[pos].push_back(root);
		father[root] = pos;
		getvson(root, dest[pos][i], 0, len[pos][i]);
		work(root);
	}
}
int query(vector <int> &a, int value) {
	int l = -1, r = a.size() - 1;
	while (l < r) {
		int mid = (l + r + 1) / 2;
		if (a[mid] <= value) l = mid;
		else r = mid - 1;
	}
	return l + 1;
}
int count(int pos, int value) {
	int ans = query(vroot[pos], value);
	int p = father[pos], q = pos;
	while (p != 0) {
		ans -= query(vson[q], value - mp[p][pos]);
		ans += query(vroot[p], value - mp[p][pos]);
		q = p;
		p = father[p];
	}
	return ans;
}
int main() {
	read(n), read(k);
	int maxv = 0;
	for (int i = 1; i <= n - 1; i++) {
		int x, y, z;
		read(x), read(y), read(z);
		chkmax(maxv, z);
		dest[x].push_back(y);
		dest[y].push_back(x);
		len[x].push_back(z);
		len[y].push_back(z);
	}
	weight[0] = n + 1;
	root = 0; cntpoints = n;
	getroot(1, 0);
	work(root);
	for (int i = 1; i <= n; i++) {
		sort(vroot[i].begin(), vroot[i].end());
		sort(vson[i].begin(), vson[i].end());
	}
	for (int i = 1; i <= n; i++) {
		int l = 0, r = maxv * n;
		while (l < r) {
			int mid = (l + r) / 2;
			if (count(i, mid) <= k) l = mid + 1;
			else r = mid;
		}
		printf("%d\n", l);
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80456229