DP slope tree optimization Codeforces 1179D

Meaning of the questions: give your tree, you can add an edge in the trees, asked to add a simple path after an edge up to how many? Simple path means the path that is not only repeated points.

Thinking: After adding an edge, the tree becomes a tree ring. Easily found, a point on the base ring subtree rooted points simple path does not increase. Therefore, the problem is equivalent to looking into a ring group, such that a point on the base ring subtree rooted Σ (i from 1 to n) sz [i] * (sz [i] - 1) / 2 the minimum. We seek to look into the conversion formula (sz [i] and the square - n) / 2. Equivalent to our request sz [i] the sum of squares. However, we do not know which is the base ring, ask how sz it? We found a property: Edge connection two points must be added to the tree degree is 1 point, otherwise, we will be able to reduce the sum of squares. So, based on this property, we can make a tree dp. Set DP [i] for the i to the root of the subtree, the path from i to select a leaf node subtree of a point on the ring, can be obtained minimum sum of squares. dp [i] = min (dp [son] + (sz [i] - sz [son]) ^ 2).

We assume that the ring is a group selected u -> lca (u, v) -> v, the path is assumed as u fu lca (u, v) in front lca (u, v) of a node, Fv Similarly, the sum of squares ans = dp [fu] + dp [fv] + (n - sz [fu] - sz [fv]) ^ 2. So, when we search deep to find all children dp value and sz, which enumeration to update the square and two children, so the worst case is O (n ^ 2), and time out. Found that the state transition equation has fu and fv product terms, we can consider the slope optimization. Transpose the equation: dp [fv] = 2 * (n - sz [fu]) * sz [fv] + (ans - dp [fu] - 2 * n * sz [fu]). Then the equivalent is sz [fv] as abscissa, dp [fv] to the vertical axis, a slope of 2 * (n - sz [fu]) of the straight line, ans to the minimum, the minimum required intercept. We sz small to large, the monotone queue maintains a convex hull, after the monotone queue to half. Details noted: After 1, binary determination is no legal need not equal the fu and fv. 2: a slope optimization fu and fv cases ranging from only consider, we need to look at special sentence from the best leaf node is connected to the current node in this case directly.

Code:

#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define LL long long
#define pll pair<LL, LL>
using namespace std;
const int maxn = 500010;
vector<int> G[maxn];
LL sz[maxn], dp[maxn];
pll q[maxn], a[maxn], b[maxn];
you are, r;
LL n, ans;
int everything;
map<pll, int> mp;
void add(int x, int y) {
	G[x].push_back(y);
	G[y].push_back(x);
}
bool check(pll x, pll y, pll z) {
	if((y.second - x.second) * (z.first - y.first) < (y.first - x.first) * (z.second - y.second))
		return 1;
	else
		return 0;
}
int binary_search(pll x, LL k) {
	if(l == r) return l;
	you L = l, r = R;
	while(L < R) {
		int mid = (L + R) >> 1;
		if((q[mid + 1].second - q[mid].second) <= k * (q[mid + 1].first - q[mid].first)) L = mid + 1;
		else R = mid; 
	}
	return L;
}
void dfs(int x, int fa) {
	No. [x] = 1;
	for (auto y : G[x]) {
		if(y == fa) continue;
		dfs(y, x);
		No. [x] + = c [gamma];
	}
	for (auto y : G[x]) {
		if(y == fa) continue;
		dp [x] = min (dp [x], (c [x] - c [gamma]) (W [x] - c [gamma]) + dp [gamma]);
	}
	tot = 0;
	for (auto y : G[x]) {
		if(y == fa) continue;
		b [++ tot] = a [y];
	}
	Luckily (b + 1 + 1 + b all);
	mp.clear();
	if(tot > 1) {
		l = 1, r = 0;
		for (int i = 1; i <= tot; i++) {
			mp [b [i]] ++;
			while(l < r && !check(q[r - 1], q[r], b[i])) r--;
			q[++r] = b[i];
		}
		for (int i = 1; i <= tot; i++) {
			int pos = binary_search(b[i], 2 * (n - b[i].first));
			if(q[pos] == b[i]) {
				if(mp[b[i]] > 1) {
					ans = min(ans, b[i].second + q[pos].second + (n - b[i].first - q[pos].first) * (n - b[i].first - q[pos].first));
				} else {
					if(pos < r) ans = min(ans, b[i].second + q[pos + 1].second + (n - b[i].first - q[pos + 1].first) * (n - b[i].first - q[pos + 1].first));
					else ans = min(ans, b[i].second + q[pos - 1].second + (n - b[i].first - q[pos - 1].first) * (n - b[i].first - q[pos - 1].first));
				}
			} else {
				ans = min(ans, b[i].second + q[pos].second + (n - b[i].first - q[pos].first) * (n - b[i].first - q[pos].first)); 
			}
		}
	}
	for (int i = 1; i <= tot; i++) {
		ans = min(ans, b[i].second + (n - b[i].first) * (n - b[i].first));
	}
	if(fa != -1 && G[x].size() == 1) dp[x] = sz[x] * sz[x];
	a[x] = make_pair(sz[x], dp[x]);
}
int main () {
	int x, y;
	memset(dp, 0x3f, sizeof(dp));
//	freopen("1179Din.txt", "r", stdin);
//	freopen("1179D1out.txt", "w", stdout);
	scanf("%lld", &n);
	for (int i = 1; i < n; i++) {
		scanf("%d%d", &x, &y);
		add(x, y);
	}
	= 1e18 years;
	dfs(1, -1);
	years = min (years dp [1]);
	years - = n;
	years / = 2;
	2ll years = * n * (n - 1) / 2ll - years;
	printf("%lld\n", ans);
} 

  

Guess you like

Origin www.cnblogs.com/pkgunboat/p/11142535.html