专栏文章

题解:P12537 [XJTUPC 2025] 罗斯飞鸽

P12537题解参与者 5已保存评论 4

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
4 条
当前快照
1 份
快照标识符
@mip9ehtk
此快照首次捕获于
2025/12/03 08:18
3 个月前
此快照最后确认于
2025/12/03 08:18
3 个月前
查看原文
出题人题解。
这个题出的时候没想过还能三维偏序。我们先考察 v=1v = 1 的情况:将判定点画在 xOtxOt 平面上,从某个判定点出发,能到达的点的范围在它的左上 45 度到右上 45 度之间。
如下:
这是第一组样例对应的情况,如果判定了 F 点,下一步可判定的就是 A,B,C 之一。
这个画图似乎对解题没有帮助?并不!我们把整个图片旋转 45 度:
所以,此时每个点能到达的下一个点,就是位于右上方的点。这是一个“二维偏序最长链问题”,如果将所有点按照新的横坐标排序,就是在求新的纵坐标的最长不下降子序列。
形式化地,新的坐标是 (t+x,tx)(t + x, t - x)
不过,完整的题目要考虑 vv。所以实际上,一个点能到达的点是一个 ±arctan(v)\pm \arctan(v) 的角度范围。以 v=2v=2 为例:
此时,我们在进行旋转运算的同时,还要向 t 轴方向做一个伸缩变换。感性理解,这两个变换显然不会改变可达点集。
形式话地说,得到的新坐标是 (vt+x,vtx)(vt+x, vt-x),然后跑最长不下降子序列就好了。
题解 pdf 里那个证明更严谨一点。
代码:
CPP
#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;
}

评论

4 条评论,欢迎与作者交流。

正在加载评论...