1 条题解
-
0
自动搬运
来自洛谷,原作者为

spire001
**搬运于
2025-08-24 21:48:09,当前版本为作者最后更新于2024-06-05 19:11:08,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P3364题解
题目大意
这个题的题面讲的十分清楚,只是你需要注意是什么大于什么,不然这种错误很不容易调试出来。
解题思路
这个题很模板,总结一下规律,解题流程是:
- 写出偏序关系(状态转移方程)。
- 打出暴力(熟练的话可以忽略)。
- 套用 cdq 分治模板。
对于这个题,我们分别记题目中的等级、力量、智力、攻击力为 。
那么等级从低到高排序保证了 关键字重复不影响答案。 剩下的关系照着题目可以写出来,它们是 ,,。
然后就可以套用 cdq 分治优化 dp 模板了。
AC代码
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #define lowbit(x) (x & -(x)) using namespace std; constexpr int N = 1e5 + 2; constexpr int M = N * 3; // 离散化后三倍空间 int n, b[N << 2], ln, c[M], ans = 1; struct node{ int a, b, c, d, dp, id; // id 方便排序回初始状态 } a[N]; inline void add(const int x, const int val) { for (int i = x; i < M; i += lowbit(i)) c[i] = max(c[i], val); return; } // 树状数组 inline int ask(const int x) { int res = 0; for (int i = x; i; i &= i - 1) res = max(res, c[i]); return res; } inline void clear(const int x) { for (int i = x; i < M; i += lowbit(i)) c[i] = 0; return; } // 清空树状数组 inline void fun(int &x) { x = lower_bound(b + 1, b + ln + 1, x) - b; return; } // 离散化 /* i < j ai <= aj di <= bj ci <= dj 偏序关系 */ void cdq(int l, int r) { if (l == r) { a[l].dp = max(a[l].dp, 1); // 这里取 max 而非直接赋值 return; } const int mid = (l + r) >> 1; cdq(l, mid); sort(a + l, a + mid + 1, [&](const node &A, const node &B) { return A.d < B.d; }); // 按照第二重偏序关系排序 sort(a + mid + 1, a + r + 1, [&](const node &A, const node &B) { return A.b < B.b; }); // 按照第二重偏序关系排序 int i = l, j = mid + 1; while (j <= r) // 双指针 { while (i <= mid && a[i].d <= a[j].b) { add(a[i].c, a[i].dp); // 按照第三重偏序关系加入树状数组 i++; } a[j].dp = max(a[j].dp, ask(a[j].d) + 1); // 按照第三重偏序关系更新答案 ans = max(ans, a[j].dp); j++; } for (int p = l; p != i; p++) clear(a[p].c); // 清空树状数组 sort(a + mid + 1, a + r + 1, [&](const node &A, const node &B) { return A.id < B.id; }); // 排序回原始状态 cdq(mid + 1, r); return; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i].a >> a[i].b >> a[i].c >> a[i].d; // b[++ln] = a[i].a; b[++ln] = a[i].b; b[++ln] = a[i].c; b[++ln] = a[i].d; // 离散化 } sort(b + 1, b + ln + 1); ln = unique(b + 1, b + ln + 1) - b - 1; for (int i = 1; i <= n; i++) { // fun(a[i].a); fun(a[i].b); fun(a[i].c); fun(a[i].d); } sort(a + 1, a + n + 1, [&](const node &A, const node &B) { return A.a < B.a; // a 关键字直接排序可不需要离散化 }); for (int i = 1; i <= n; i++) a[i].id = i; // id 方便排序回去 cdq(1, n); // for (int i = 1; i <= n; i++) cout << a[i].dp << ' '; cout << ans; // 对 dp 取 max 并输出答案 return 0; } /* begin: 2024年6月5日17:28:02 debug: 2024年6月5日18:23:49 finish: 2024年6月5日19:00:08 */
- 1
信息
- ID
- 1885
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者