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;
}

浙公网安备 33010602011771号