复杂度 O(n (logn)^2) TLE
查看原帖
复杂度 O(n (logn)^2) TLE
760266
xvl_楼主2024/7/16 10:27

思路是对于每一个结点 uu,二分找最多有几个祖先能够控制 uu,然后用树上差分维护祖先能控制的结点数。整个的复杂度应该(?)是 O(n(log⁡n)2)O(n (\log_n)^2) 的,但是 TLE 了。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
struct Edge { ll to, w; };
ll n, sum;
ll fa[200005][20], lvl[200005], a[200005], dis[200005], c[200005];
vector <Edge> G[200005];
void dfs(ll cur, ll p) {
	lvl[cur] = lvl[p] + 1;
	fa[cur][0] = p;
	for (int i = 1; i <= 19; i++) fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
	for (auto v : G[cur]) {
		if (v.to == p) continue;
		dis[v.to] = dis[cur] + v.w;
		dfs(v.to, cur);
	}
}
ll LCA(ll u, ll v) {
	if (lvl[u] < lvl[v]) swap(u, v);
	for (int i = 19; i >= 0; i--) {
		if ((lvl[u] - lvl[v] >> i) & 1) u = fa[u][i];
	}
	if (u == v) return u;
	for (int i = 19; i >= 0; i--) {
		 if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
	}
	return fa[u][0];
}
ll DIS(ll u, ll v) { return dis[u] + dis[v] - 2 * dis[LCA(u, v)]; }
ll pr(ll u, ll k) {
	for (int i = 19; i >= 0; i--) {
		if ((k >> i) & 1) u = fa[u][i];
	}
	return u;
}
void dfs_sum(ll cur, ll p) {
	for (auto v : G[cur]) {
		if (v.to == p) continue;
		dfs_sum(v.to, cur);
		c[cur] += c[v.to];
	}
}
int main() {
	ios :: sync_with_stdio(0);
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i < n; i++) {
		ll p, w;
		cin >> p >> w;
		G[i + 1].push_back({p, w});
		G[p].push_back({i + 1, w});
	}
	lvl[0] = -1;
	dfs(1, 0);
	for (int i = 1; i <= n; i++) {
		ll l = 0, r = lvl[i];
		while (l <= r) {
			ll mid = l + r >> 1;
			if (DIS(pr(i, mid), i) <= a[i]) {
				sum = mid;
				l = mid + 1;
			}
			else r = mid - 1;
		}
		// cout << i << ' ' << pr(i, sum) << '\n';
		if (pr(i, sum) != i) {
			ll p = fa[i][0];
			c[p]++, c[pr(i, sum)]++;
			c[LCA(p, pr(i, sum))]--, c[fa[LCA(p, pr(i, sum))][0]]--;
		}
	}
	dfs_sum(1, 0);
	for (int i = 1; i <= n; i++) cout << c[i] << ' ';
	return 0;
}
 
2024/7/16 10:27
加载中...