mxqz 点分治 + 主席树
查看原帖
mxqz 点分治 + 主席树
307535
Custlo0793楼主2022/6/15 14:14

TLE #5

#include <bits/stdc++.h>
#define int long long

using namespace std;

const int N = 1e5 + 5;

struct RANKED_SGT {
	int tot, sum[N << 5], lc[N << 5], rc[N << 5];
	inline void init () {
		tot = 0, memset(sum, 0, sizeof(sum));
		memset(lc, 0, sizeof(lc)), memset(rc, 0, sizeof(rc));
		return ;
	}
	inline void modify (int & u, int v, int l, int r, int pos, int k) {
		u = ++ tot, sum[u] = sum[v] + k, lc[u] = lc[v], rc[u] = rc[v];
		if (l == r) return ;
		int mid = (l + r) / 2;
		if (pos <= mid) modify(lc[u], lc[v], l, mid, pos, k);
		else modify(rc[u], rc[v], mid + 1, r, pos, k);
	}
	inline int query (int u, int l, int r, int p, int q) {
		if (! u) return 0;
		if (p <= l && r <= q) return sum[u];
		int mid = (l + r) / 2, ans = 0;
		if (p <= mid) ans += query(lc[u], l, mid, p, q);
		if (q > mid) ans += query(rc[u], mid + 1, r, p, q);
		return ans;
	}
} t;

struct EDGE {
	int v, w;	
} ;

vector <EDGE> son[N];

inline void AddEdge (int u, int v, int w) { son[u].push_back(EDGE{v, w}); }

struct path {
	int d1, d2;
	inline bool operator < (const path & x) const {
		return d2 < x.d2;
	}
} arr[N];

int n, ans, tot, w, l, siz[N], mas[N], vis[N], pos[N];

inline void getRoot (int u, int fa, int & rt, int s) {
	siz[u] = 1, mas[u] = 0;
	for (auto v : son[u]) 
		if (! vis[v.v] && v.v != fa) {
			getRoot(v.v, u, rt, s), siz[u] += siz[v.v];
			mas[u] = max(mas[u], siz[v.v]);
		}
	mas[u] = max(mas[u], s - siz[u]);
	if (mas[u] < mas[rt]) rt = u;
}
inline void getDist (int u, int fa, int d1, int d2) {
	if (d1 > l || d2 > w) return ;
	arr[++ tot] = path{d1, d2};
	for (auto v : son[u])
		if (! vis[v.v] && v.v != fa)
			getDist(v.v, u, d1 + 1, d2 + v.w);
}
inline int calc (int u, int d1, int d2) {
	tot = 0, t.init(), getDist(u, 0, d1, d2);
	sort (arr + 1, arr + 1 + tot);
	int res = 0;
	for (int i = 1; i <= tot; i ++) t.modify(pos[i], pos[i - 1], 0, n, arr[i].d1, 1);
	for (int i = 1; i <= tot; i ++) {
		int v = upper_bound(arr + 1, arr + 1 + tot, path{0, w - arr[i].d2}) - arr - 1;
		res += t.query(pos[v], 0, n, 0, l - arr[i].d1);
		if (2 * arr[i].d1 <= l && 2 * arr[i].d2 <= w) res ++;
	}
    return res / 2;
}
inline void solve (int u) {
	ans += calc(u, 0, 0), vis[u] = 1;
	int rt;
	for (auto v : son[u]) 
		if (! vis[v.v]) {
			ans -= calc(v.v, 1, v.w);
			rt = 0, getRoot(v.v, 0, rt, siz[v.v]);
			solve(rt);
		}
}
signed main () {
	cin >> n >> l >> w;
	for (int i = 2, v, w; i <= n; i ++) {
		scanf("%lld%lld", & v, & w);
		AddEdge(i, v, w), AddEdge(v, i, w);
	}
	int rt = 0;
	mas[0] = 114514114541, getRoot(1, 0, rt, n), solve(rt);
	cout << ans - n;
	return 0;
}

160696793#

2022/6/15 14:14
加载中...