F - Cat exercise Editorial by newsname


Construct a max-heap Cartesian tree from the height array, where:
- The tree is built such that values form a max-heap, and indices follow an in-order traversal.
- The root corresponds to the position of the tower with height \(N\).
- For any node \(u\), its left/right subtree exactly represents the interval on \(.u\) .’s left/right that is blocked by taller elements. The root of this subtree is the tallest tower within that interval.

When the cat is on node \(u\) and we decide to remove \(u\) now, the cat’s next jump must land on the tallest remaining tower in its reachable interval. If we pre-remove taller towers that we do not want to compete (since removing them does not affect the cat’s movement), the “tallest remaining tower” can be directed to a child root of \(u\), and we can recursively repeat this process within that subtree.

Thus, the cat’s trajectory must be a downward chain from the root (it remains in a single subtree and can never cross back to the other side). To maximize the total distance, intermediate nodes on the chain should not be skipped: in one-dimensional space, \(|x - z| \leq |x - y| + |y - z|\), so passing through the subtree root before proceeding downward only lengthens the total distance.

Define \(f(u)\) as the maximum total distance achievable when the cat is at node ( u ) and only ( u )’s entire subtree is retained. Then: \(f(u) = \max\left( |u - L(u)| + f(L(u)),\ |u - R(u)| + f(R(u)) \right)\) with the base case \( f(u) = 0 \)if \(u\) has no children. Here, \(u\), \( L(u)\), and \(R(u)\) directly refer to index positions, and the distance is the absolute difference of indices.

code(c++):

int n, p[maxn], lc[maxn], rc[maxn], par[maxn], stk[maxn], top, sn[maxn], fl[maxn], dp[maxn];
signed main() {
	t(n);
	le(i, 1, n) t(p[i]);
	le(i, 1, n) {
		int last = 0;
		while (top && p[stk[top]] < p[i]) last = stk[top--];
		if (top) {
			rc[stk[top]] = i;
			par[i] = stk[top];
		}
		if (last) {
			lc[i] = last;
			par[last] = i;
		}
		stk[++top] = i;
	}
	int r = 0;
	for (int i = 1; i <= n; i++) if (p[i] == n) r = i;
	int sp = 0;
	sn[++sp] = r;
	fl[sp] = 0;
	while (sp) {
		int u = sn[sp], f = fl[sp];
		--sp;
		if (!f) {
			sn[++sp] = u;
			fl[sp] = 1;
			if (rc[u]) sn[++sp] = rc[u], fl[sp] = 0;
			if (lc[u]) sn[++sp] = lc[u], fl[sp] = 0;
		} else {
			int ans = 0;
			if (lc[u]) ans = max(ans, abs(u - lc[u]) + dp[lc[u]]);
			if (rc[u]) ans = max(ans, abs(u - rc[u]) + dp[rc[u]]);
			dp[u] = ans;

		}
	}
	cout << dp[r];
	return 0;
}

posted:
last update: