专栏文章

姉の彼女にキスをした

P14439题解参与者 2已保存评论 1

文章操作

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

当前评论
1 条
当前快照
1 份
快照标识符
@min15xa3
此快照首次捕获于
2025/12/01 18:52
3 个月前
此快照最后确认于
2025/12/01 18:52
3 个月前
查看原文
宝宝题。
首先暴力 dp。把起点和终点放在 T0T_0Tn+1T_{n+1},记 fif_i 表示不停跳直到到达 TiT_i 休息,此时体力最大值。枚举上一个休息位置 jj,中间为了减少损耗一定尽量少跳,转移 fiBi+fjATiTjDf_i\gets B_i+f_j-A\left\lceil\dfrac{T_i-T_j}{D}\right\rceil。暴力做到 O(n2)O(n^2)
考察后面的上取整,注意到:
abD=aDbD+[amodDbmodD]\left\lceil\dfrac{a-b}{D}\right\rceil=\left\lfloor\dfrac{a}{D}\right\rfloor-\left\lfloor\dfrac{b}{D}\right\rfloor+[a\bmod D \ge b\bmod D]
其中 aa 已经确定是 PiP_i,最大化后面有关 bb 的下取整以及艾弗森括号。于是我们转移的同时维护 txt_x 表示 Pix(modD)P_i\equiv x\pmod D 对应的 Fi+APiDF_i+A\left\lfloor\dfrac{P_i}{D}\right\rfloormax\max。艾弗森括号在 x<amodDx < a\bmod D 时不成立,大于时成立,对两种情况分别求出 tt 的区间 max\max 计算答案即可,支持单点 chkmax 区间最大值,动态开点线段树简单做到 O(nlogV)O(n\log V)
CPP
#include <bits/stdc++.h>
#define LL long long
#define ull unsigned long long
#define uint unsigned int
using namespace std;
const int N = 1e5 + 10;
int n, P[N], Q[N], D, A;
LL F[N];

int ptot, rt, ls[N * 30], rs[N * 30]; LL tr[N * 30];
void update(int& p, int l, int r, int x, LL k) {
	if (!p) p = ++ ptot;
	if (l == r) { tr[p] = k; return ; }
	int mid = (l + r) >> 1;
	if (x <= mid) update(ls[p], l, mid, x, k);
	else update(rs[p], mid + 1, r, x, k);
	tr[p] = max(tr[ls[p]], tr[rs[p]]); return ;
}
LL query(int p, int l, int r, int x, int y) {
	if (!p || x > r || y < l) return -1e18;
	if (x <= l && y >= r) return tr[p];
	int mid = (l + r) >> 1;
	return max(query(ls[p], l, mid, x, y), query(rs[p], mid + 1, r, x, y));
}

int main() {
	freopen(".in", "r", stdin); freopen(".out", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
	tr[0] = -1e18;
	int s, t; cin >> s >> t >> D >> A >> n; P[0] = s, P[n + 1] = t;
	for (int i = 1; i <= n; i ++) cin >> P[i] >> Q[i];
	memset(F, -0x3f, sizeof F); F[0] = 0;
	update(rt, 0, D, P[0] % D, F[0] + 1ll * P[0] / D * A);
	for (int i = 1; i <= n + 1; i ++) {
		int p = P[i] % D;
		F[i] = Q[i] + max(query(rt, 0, D, 0, p - 1), query(rt, 0, D, p, D) + A) - 1ll * P[i] / D * A - A;
		update(rt, 0, D, p, F[i] + 1ll * P[i] / D * A);
	}
	cout << F[n + 1] << "\n";
	return 0;
}

评论

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

正在加载评论...