CF2195F Parabola Independence 题解

原题链接
题目翻译

Solution

可定义全体二次函数的严格偏序关系 \(\prec\)\(f \prec g \iff f(x) < g(x) , \ \forall x \in \mathbb{R}\)。二次函数 \(f\)\(g\) 是 independent 的当且仅当 \(f \prec g\)\(g \prec f\)。假设 \(f \prec g\),则在 \(\prec\) 的 Hasse 图上存在一条以 \(f\) 为起点、\(g\) 为终点的路径,从而知 \(G\) 是 organized 的当且仅当存在一条可串联 \(G\) 中所有点的路径。求 \(s_i := \max\{|G|: f_i \in G\}\),等价于求经过 \(f_i\) 的最长链长度。

在 DAG 中求经过定点的最长链,可通过求以该定点为起点的最长链 + 取反图的方式实现,其中前者可由拓扑排序 + DP 实现,具体可见洛谷P1137 旅行计划

拓扑排序并不需要用 Kahn 算法, 实际上,对所有的 \(f\) ,优先对二次项系数升序排序,如果二次项系数相等再按照常数项系数升序排序,如此即可得到已拓扑排序的二次函数序列。

DP 过程对应的 DAG 实际是 Hasse 图的传递闭包,于是 DP 过程中需要判断两个二次函数 \(f\)\(g\) 是否是 independent 的,具体判断方法需要对二次项系数 \(a_f\)\(a_g\) 分类讨论。

  • 如果 \(a_f \ne a_g\),则 \(h:=f-g\) 是二次函数,通过 \(h\) 的判别式即可判断;
  • 如果 \(a_f = a_g\),则 \(h:=f-g\) 是一次函数或常值函数,当且仅当 \(h\) 是非零常值函数时 \(f\)\(g\) 是 independent 的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 3E3 + 5;

ll n, dp1[MAXN], dp2[MAXN], ans[MAXN];

struct F {
	ll a, b, c, i;
} f[MAXN];

bool cmp(F x, F y) {
	return x.a < y.a || (x.a == y.a && x.c < y.c);
}

bool beIndependent(ll i, ll j) {
	ll da = f[i].a - f[j].a, db = f[i].b - f[j].b, dc = f[i].c - f[j].c;
	return db * db < 4 * da * dc || (da == 0 && db == 0 && dc != 0);
}

void solve() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; ++i)
		scanf("%lld%lld%lld", &f[i].a, &f[i].b, &f[i].c), f[i].i = i;
	sort(f + 1, f + n + 1, cmp);
	for (int i = 1; i <= n; ++i)
		dp1[i] = dp2[i] = 1;
	for (int i = 2; i <= n; ++i)
		for (int j = 1; j < i; ++j)
			if (beIndependent(i, j))
				dp1[i] = max(dp1[i], dp1[j] + 1);
	for (int i = n - 1; i >= 1; --i)
		for (int j = n; j > i; --j)
			if (beIndependent(i, j))
				dp2[i] = max(dp2[i], dp2[j] + 1);
	for (int i = 1; i <= n; ++i)
		ans[f[i].i] = dp1[i] + dp2[i] - 1;
	for (int i = 1; i <= n; ++i)
		printf("%lld ", ans[i]);
	printf("\n");
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--)
		solve();
	return 0;
}
posted @ 2026-03-31 11:37  SHUddol  阅读(4)  评论(0)    收藏  举报