CodeForces 1842E Tenzing and Triangle

洛谷传送门

CF 传送门

一个很显然的观察:选择的三角形两两重叠面积为 \(0\),否则合并更优。

考虑 dp,设 \(f_i\) 为删完 \(x_j \ge i\) 的所有点的最小花费。转移就枚举选择的三角形直角边长 \(l\),那么 \(f_i = \min(f_{i + 1} + \sum\limits_{x_p = i} c_p, \min\limits_l f_{i + l} + \sum\limits_{i \le x_p < i + l \land y_p < k - i - l} c_p)\),就是把三角形下方的那坨矩形的点的 \(c_i\) 算进去。

考虑直接线段树维护后面那坨式子的最小值,设 \(g_j = \sum\limits_{i \le x_p < j \land y_p < k - j} c_p\)\(i + 1 \to i\) 时,对于每个 \(x_p = i\) 的点,让 \(g_{i + 1 \sim k - y_p - 1}\) 加上 \(c_p\) 即可。

时间复杂度 \(O((n + k) \log k)\)

code
// Problem: E. Tenzing and Triangle
// Contest: Codeforces - CodeTON Round 5 (Div. 1 + Div. 2, Rated, Prizes!)
// URL: https://codeforces.com/contest/1842/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;
const ll inf = 0x3f3f3f3f3f3f3f3fLL;

ll n, m, K, f[maxn], g[maxn];
vector<pii> vc[maxn];

struct node {
	ll x, y, z;
} a[maxn];

namespace SGT {
	ll tree[maxn << 2], tag[maxn << 2];
	
	inline void pushup(int x) {
		tree[x] = min(tree[x << 1], tree[x << 1 | 1]);
	}
	
	inline void pushdown(int x) {
		if (!tag[x]) {
			return;
		}
		tree[x << 1] += tag[x];
		tree[x << 1 | 1] += tag[x];
		tag[x << 1] += tag[x];
		tag[x << 1 | 1] += tag[x];
		tag[x] = 0;
	}
	
	void build(int rt, int l, int r) {
		tree[rt] = inf;
		if (l == r) {
			return;
		}
		int mid = (l + r) >> 1;
		build(rt << 1, l, mid);
		build(rt << 1 | 1, mid + 1, r);
	}
	
	void update(int rt, int l, int r, int ql, int qr, ll x) {
		if (ql > qr) {
			return;
		}
		if (ql <= l && r <= qr) {
			tree[rt] += x;
			tag[rt] += x;
			return;
		}
		pushdown(rt);
		int mid = (l + r) >> 1;
		if (ql <= mid) {
			update(rt << 1, l, mid, ql, qr, x);
		}
		if (qr > mid) {
			update(rt << 1 | 1, mid + 1, r, ql, qr, x);
		}
		pushup(rt);
	}
	
	void modify(int rt, int l, int r, int x, ll y) {
		if (l == r) {
			tree[rt] = y;
			return;
		}
		pushdown(rt);
		int mid = (l + r) >> 1;
		(x <= mid) ? modify(rt << 1, l, mid, x, y) : modify(rt << 1 | 1, mid + 1, r, x, y);
		pushup(rt);
	}
}

void solve() {
	scanf("%lld%lld%lld", &n, &K, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld%lld%lld", &a[i].x, &a[i].y, &a[i].z);
		vc[a[i].x].pb(a[i].y, a[i].z);
		g[a[i].x] += a[i].z;
	}
	SGT::build(1, 0, K);
	mems(f, 0x3f);
	f[K] = 0;
	SGT::modify(1, 0, K, K, K * m);
	for (int i = K - 1; ~i; --i) {
		f[i] = f[i + 1] + g[i];
		for (pii p : vc[i]) {
			SGT::update(1, 0, K, i + 1, K - p.fst - 1, p.scd);
		}
		f[i] = min(f[i], SGT::tree[1] - m * i);
		SGT::modify(1, 0, K, i, f[i] + m * i);
	}
	printf("%lld\n", f[0]);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2023-06-25 18:47  zltzlt  阅读(145)  评论(0)    收藏  举报