0%

Codeforces Round 1080 (Div. 3)(CF-1080)——F. Parabola Independence(寻找传递性)(寻找最长链使用记忆化 dfs)(边的数量也会影响记忆化 DFS 的时间复杂度)(小心二次函数的退化)

题目大意

题意

给定 nn 个二次函数 F={f1,f2,,fn}F=\{f_1, f_2, \dots, f_n\},其中 fi(x)=aix2+bix+cif_i(x) = a_i x^2 + b_i x + c_i

定义两个函数 ffgg独立 的,当且仅当对于所有的实数 xRx \in \mathbb{R},都有 f(x)g(x)f(x) \neq g(x)(即两个函数的图像在平面上没有交点)。

定义一个函数集合 GFG \subseteq F有序 的,当且仅当 GG 中任意两个不同的函数都是独立的。

对于每一个 ii (1in1 \le i \le n),请计算包含 fif_i 的最大有序子集的大小(即寻找一个最大的子集 SFS \subseteq F,使得 fiSf_i \in SSS 是有序的,输出 S|S|)。

数据范围

  • 1t1041 \le t \le 10^4

  • 1n30001 \le n \le 3000

  • 106ai,bi,ci106,ai0-10^6 \le a_i, b_i, c_i \le 10^6, a_i \neq 0

  • 保证所有测试用例中 n2n^2 的总和不超过 300023000^2

输入格式

第一行包含一个整数 tt,表示测试用例的数量。
对于每个测试用例,第一行包含一个整数 nn
接下来的 nn 行,每行包含三个整数 ai,bi,cia_i, b_i, c_i,描述第 ii 个二次函数。

输出格式

对于每个测试用例,输出一行 nn 个整数,第 ii 个整数表示包含 fif_i 的最大有序子集的大小。

样例输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
3
4
1 2 -1
-3 0 -3
-1 4 -5
1 2 -4
5
3 0 0
1 0 -5
-3 0 0
-1 0 10
1 0 -10
5
884 -667 497
680 -973 213
23 -548 -412
826 359 -333
773 212 218

样例输出

1
2
3
3 2 3 3
3 3 2 2 3
3 3 3 1 2

样例解释(第一组数据)

给定的 4 个函数如下:

  1. f1(x)=x2+2x1f_1(x) = x^2 + 2x - 1

  2. f2(x)=3x23f_2(x) = -3x^2 - 3

  3. f3(x)=x2+4x5f_3(x) = -x^2 + 4x - 5

  4. f4(x)=x2+2x4f_4(x) = x^2 + 2x - 4

各函数包含于其中的最大有序子集如下:

  • 对于 f1f_1:集合 {f1,f3,f4}\{f_1, f_3, f_4\} 是有序的(两两无交点),大小为 3。

  • 对于 f2f_2:集合 {f1,f2}\{f_1, f_2\} 是有序的,大小为 2。

  • 对于 f3f_3:集合 {f1,f3,f4}\{f_1, f_3, f_4\} 是有序的,大小为 3。

  • 对于 f4f_4:集合 {f1,f3,f4}\{f_1, f_3, f_4\} 是有序的,大小为 3。

image

思路讲解

2025 United Kingdom and Ireland Programming Contest (UKIEPC 2025) 2025 英国 ICPC——J. Joust Sort(拓扑排序解决依赖排序问题)

那么我们实际上可以使用记忆化的 DFS 去解决这个问题。

实际上来说呢,如果这个图它是一个完全图,它没有任何其他的性质的话,实际上是一个 NP 问题,也就是团问题。因此呢,实际上这个关系之间具有严格偏序关系。因此这个图实际上是一个 DAG。我们是就是要在一个 DAG 上去求包含该节点的一个最长链。

那么其实不难想到,这个是真不难想到,就是你去求包含一个节点的最长链的话,直接去求是比较困难的。你可以求,先求以这个点为起点的最长链(长度),再去求以这个点为终点的最长链(长度)。

不过其实求以这个点为终点的最长链的长度,你可能会说,哎,我不会求啊,这个怎么求?哎,实际上很简单,你就把图所有的边全部反向,然后再用跑,这个求以这个点为起点的最长链长度再跑一遍就好了。

实际上来说,这个东西,这个记忆化 DFS 能跑,也是因为这张图具有 DAG 性质。你实在不放心,也可以用拓扑排序去跑一个 DP 也不难,反正。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
auto solve=[&](vector<ll> &mx_chain,const vector<vector<ll>> &g) -> void {
// 以 i 为根的,为链的起点的,记忆化 dfs 数组
vector<ll> dp(N+2);
vector<char> vis(N+2);
auto dfs=[&](auto && self,ll u) -> void {
if (vis[u]) {
return;
}
vis[u]=true;
for (auto to:g[u]) {
// if (vis[to]) continue;
self(self,to);
dp[u]=max(dp[u],dp[to]);
}
dp[u]+=1;
};
for (int i=1;i<=N;++i) {
dfs(dfs,i);
mx_chain[i]=dp[i];
}
};
solve(mx_chain1,org_g);
solve(mx_chain2,rev_g);

AC代码

AC
https://codeforces.com/contest/2195/submission/363306906

心路历程(WA,TLE,MLE……)