56 pts求卡常玄关
查看原帖
56 pts求卡常玄关
637796
Xy_top楼主2024/9/27 00:16

目前大样例 5 用时 5s,应该不是代码写挂了。

#include <bits/stdc++.h>
#define int long long
#define For(i, a, b) for (int i = (a); i <= (b); i ++)
#define foR(i, a, b) for (int i = (a); i >= (b); i --)
using namespace std;
int n, m, k, d, mx;
int cnt, b[800005], dp[800005];
int mxx[2400005], tag[2400005];
vector <int> v[800005];
struct chall {int x, y, d, len;}a[100005];
bool cmp (chall c1, chall c2) {return c1.y < c2.y;}
inline int read () {
	char ch = getchar ();
	int x = 0;
	while (ch < '0' || ch > '9') ch = getchar ();
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - 48;
		ch = getchar ();
	}
	return x;
}
void pushdown (int l, int r, int k) {
	if (tag[k]) {
		mxx[k << 1] += tag[k];
		mxx[k << 1 | 1] += tag[k];
		tag[k << 1] += tag[k];
		tag[k << 1 | 1] += tag[k];
		tag[k] = 0;
	}
}
inline void update (int l, int r, int k, int x, int y, int v) {
	if (x > y) return;
	if (x <= l && y >= r) {
		mxx[k] += v;
		tag[k] += v;
		return;
	}
	pushdown (l, r, k);
	int mid = l + r >> 1;
	if (x <= mid) update (l, mid, k << 1, x, y, v);
	if (y > mid) update (mid + 1, r, k << 1 | 1, x, y, v);
	mxx[k] = max (mxx[k << 1], mxx[k << 1 | 1]);
}
inline int query (int l, int r, int k, int x, int y) {
	if (x > y) return 0;
	if (x <= l && y >= r) return mxx[k];
	pushdown (l, r, k);
	int mid = l + r >> 1, res = -1000000000000000000;
	if (x <= mid) res = query (l, mid, k << 1, x, y);
	if (y > mid) res = max (res, query (mid + 1, r, k << 1 | 1, x, y) );
	return res;
}
void solve () {
	n = read ();
	m = read ();
	k = read ();
	d = read ();
	For (i, 1, m) {
		a[i].y = read ();
		a[i].len = read ();
		a[i].d = read ();
		a[i].x = a[i].y - a[i].len + 1;
		b[++ cnt] = a[i].y; if (a[i].y != 1) b[++ cnt] = a[i].y - 1; b[++ cnt] = a[i].y + 1;
		b[++ cnt] = a[i].x; if (a[i].x != 1) b[++ cnt] = a[i].x - 1; b[++ cnt] = a[i].x + 1;
	}
	sort (b + 1, b + cnt + 1);
	cnt = unique (b + 1, b + cnt + 1) - b;
	For (i, 1, m) {
		a[i].x = lower_bound (b + 1, b + cnt + 1, a[i].x) - b;
		a[i].y = lower_bound (b + 1, b + cnt + 1, a[i].y) - b;
		mx = max (mx, a[i].y);
	}
	sort (a + 1, a + m + 1, cmp);
	For (i, 1, m) v[a[i].y].push_back (i);
	For (i, 1, mx) update (1, mx, 1, i, i, b[i] * d);
	int sum = 0;
	//第 j 个位置存储 b[j] - query (j - 1)
	//其中 query(j) 指 sum (j...n),则修改 i 时,query (1...i + 1) 都要做修改 
	For (i, 1, mx) {
		dp[i] = dp[i - 1];
		if (v[i].empty () ) {
			if (i + 2 <= mx) update (1, mx, 1, i + 2, i + 2, dp[i]);
			continue;
		}
		For (j, 0, v[i].size () - 1) {
			update (1, mx, 1, a[v[i][j] ].x + 1, mx, -a[v[i][j] ].d);
			sum += a[v[i][j] ].d;
		}
		int j = i;
		foR (l, 17, 0) if (j > (1 << l) && b[i] - b[j - (1 << l)] + 1 <= k) j -= 1 << l;
		dp[i] = max (dp[i], sum - b[i] * d - d + query (1, mx, 1, j, i) );
		if (i + 2 <= mx) update (1, mx, 1, i + 2, i + 2, dp[i]);
//		for (int j = i + 1; j >= 2 && b[i] - b[j + 1] + 1 <= k; j --) {
//			dp[i] = max (dp[i], (j >= 2 ? dp[j - 2] : 0) + sum - b[i] * d - d - query (j - 1) + b[j] * d);
//		}
	}
	cout << dp[mx];
	n = m = k = d = cnt = 0;
	For (i, 1, 800000) b[i] = dp[i] = 0;
	For (i, 1, 4 * mx) mxx[i] = tag[i] = 0;
	For (i, 1, mx) v[i].clear ();
}
signed main () {
	int _ = 1;
	cin >> _ >> _;
	while (_ --) {
		solve ();
		cout << '\n';
	}
	return 0;
}
2024/9/27 00:16
加载中...