CF777E题解

发布时间 2023-10-28 14:13:59作者: Kazdale
  • 分析

    看到这个题就想到了二维偏序。
    你们很自然地,以 \(b\) 为第一关键字降序排序,当有若干个片 \(b\) 相等时,我们发现由于 \(a < b\),所以排到最后的片一定能把这些 \(b\) 相等的片都统计上,而前面的片能否统计是依赖于 \(b\),所以考虑如何让后面的片更好统计,显然 \(a\) 越小越好统计,于是将 \(a\) 降序排序。
    我们可以直接从前向后 DP,因为在前面的点的 \(b\) 必然不小于当前 \(b\),所以我们在转移的时候只需要考虑转移 \(a\) 小于当前 \(b\) 的数,那么直接想到二维偏序的做法,将 DP 值存入 \(a\) 下标,用线段树快速统计 \([1,b-1]\)(即 \([1,b)\)) 下标范围内最大值转移,然后再将新的 DP 值存入当前 \(a\) 下标。
    这样总时间复杂度就是 \(\mathcal{O(n \log n)}\),可以通过本题。

  • 代码

#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
constexpr int MAXN(1000007);
int maxn[MAXN], lazy[MAXN], w[MAXN];
int n, tot;
inline void read(int &temp) { cin >> temp; }
struct node{
	int a, b, h;
	friend bool operator < (node x, node y) {
		if (x.b == y.b)  return x.a > y.a;
		return x.b > y.b;
	}
}a[MAXN];
struct SGT{
	#define ls (p << 1)
	#define rs (p << 1 | 1)
	#define mid ((l + r) >> 1)
	inline void pushup(int p) { maxn[p] = max(maxn[ls], maxn[rs]); }
	inline void pushdown(int p) {
		maxn[ls] = max(maxn[ls], lazy[p]), maxn[rs] = max(maxn[rs], lazy[p]);
		lazy[ls] = max(lazy[ls], lazy[p]), lazy[rs] = max(lazy[rs], lazy[p]);
		lazy[p] = 0;
	}
	void update(int p, int l, int r, int x, int val) {
		if (l == r)  return maxn[p] = max(maxn[p], val), lazy[p] = max(maxn[p], val), void();
		if (lazy[p])  pushdown(p);
		if (x <= mid)  update(ls, l, mid, x, val);
		else  update(rs, mid + 1, r, x, val);
		pushup(p);
	}
	int query(int p, int l, int r, int s, int t) {
		if (s <= l && t >= r)  return maxn[p];
		if (lazy[p])  pushdown(p);
		int res(0);
		if (s <= mid)  res = max(res, query(ls, l, mid, s, t));
		if (t > mid)  res = max(res, query(rs, mid + 1, r, s, t));
		return res;
	}
}Miku;
signed main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	read(n);
	for (int i(1); i <= n; ++i)  read(a[i].a), read(a[i].b), read(a[i].h), w[++tot] = a[i].a, w[++tot] = a[i].b;
	sort(w + 1, w + tot + 1);
	tot = unique(w + 1, w + tot + 1) - w - 1;
	for (int i(1); i <= n; ++i)  a[i].a = lower_bound(w + 1, w + tot + 1, a[i].a) - w, a[i].b = lower_bound(w + 1, w + tot + 1, a[i].b) - w;
	sort(a + 1, a + n + 1);
	for (int i(1); i <= n; ++i) {
		int x = Miku.query(1, 1, tot, 1, a[i].b - 1);
		Miku.update(1, 1, tot, a[i].a, x + a[i].h);
	}
	cout << Miku.query(1, 1, tot, 1, tot) << endl;
	return 0;
}