题解:P12537 [XJTUPC 2025] 罗斯飞鸽
出题人题解。
这个题出的时候没想过还能三维偏序。我们先考察
如下:
这是第一组样例对应的情况,如果判定了 F 点,下一步可判定的就是 A,B,C 之一。
这个画图似乎对解题没有帮助?并不!我们把整个图片旋转 45 度:
所以,此时每个点能到达的下一个点,就是位于右上方的点。这是一个“二维偏序最长链问题”,如果将所有点按照新的横坐标排序,就是在求新的纵坐标的最长不下降子序列。
形式化地,新的坐标是
不过,完整的题目要考虑
此时,我们在进行旋转运算的同时,还要向 t 轴方向做一个伸缩变换。感性理解,这两个变换显然不会改变可达点集。
形式话地说,得到的新坐标是
题解 pdf 里那个证明更严谨一点。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN(5e5 + 5);
struct Node {
long long ta, tb;
};
int n;
long long v;
Node a[MAXN], len[MAXN];
bool operator<(Node x, Node y) {
return x.ta != y.ta ? x.ta < y.ta : x.tb < y.tb;
}
bool compare(Node x, Node y) {
return x.tb != y.tb ? x.tb < y.tb : x.ta < y.ta;
}
void solve() {
scanf("%d %lld", &n, &v);
for (int i = 1; i <= n; i++) {
long long t, x;
scanf("%lld %lld", &t, &x);
a[i].ta = v * t + x;
a[i].tb = v * t - x;
}
sort(a + 1, a + n + 1, compare);
int ans = 0;
len[0].ta = len[0].tb = LLONG_MIN;
for (int i = 1; i <= n; i++) {
int p = lower_bound(len, len + ans + 1, a[i]) - len;
len[p] = a[i];
if (p > ans) ans++;
}
printf("%d\n", ans);
}
int main() {
int _;
scanf("%d", &_);
while (_--) {
solve();
}
return 0;
}