CF500F New Year Shopping Sol
线段树分治板题。
对于这道题目,看到时间点,想到对时间轴建树,对于每一次插入和删除操作,都在线段树区间上进行区间修改(标记)来完成。
具体保证时间复杂度的方法其实和线段树是一样的。
就是一段区间可以分为 级别的多段区间。
类似于线段树的区间分解,分别对区间进行 tag
标记。
显然复杂度为 ,保证了全局 的优秀复杂度。
对于 DP,可以维护一个 DP 数组,分为 层。
对于每一层下放,可以直接复制上一层的 DP 数组。
随后加入当前区间标记过的所有物品,进行 DP 即可。
具体可以看代码。
#include <bits/stdc++.h>
#define ls ((rt) << 1)
#define rs ((rt) << 1 | 1)
#define pb push_back
#define mp make_pair
#define int long long
using namespace std;
template <typename T> inline void read(T &x) {
x = 0; char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
}
const int N = 2e4 + 10;
int n, p, Q, res[N], dp[21][N];
vector <pair <int, int> > qry[N], t[N << 2];
inline void upd(int rt, int l, int r, int L, int R, int c, int h) {
if (L <= l && r <= R) return t[rt].pb(mp(c, h)), void();
int mid = (l + r) >> 1;
if (L <= mid) upd(ls, l, mid, L, R, c, h);
if (R > mid) upd(rs, mid + 1, r, L, R, c, h); return ;
}
inline void dfs(int rt, int l, int r, int dep) {
for (int i = 0; i <= 4000; ++i) dp[dep][i] = dp[dep - 1][i];
for (auto souv: t[rt]) {
for (int i = 4000; i >= souv.first; --i)
dp[dep][i] = max(dp[dep][i], dp[dep][i - souv.first] + souv.second);
}
if (l == r) {
for (auto q: qry[l]) res[q.first] = dp[dep][q.second];
return ;
}
int mid = (l + r) >> 1;
dfs(ls, l, mid, dep + 1), dfs(rs, mid + 1, r, dep + 1);
return ;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> p;
for (int i = 1; i <= n; ++i) {
int c, h, t; cin >> c >> h >> t;
upd(1, 1, 20000, t, t + p - 1, c, h);
}
cin >> Q;
for (int i = 1; i <= Q; ++i) {
int a, b; cin >> a >> b;
qry[a].pb(mp(i, b));
}
dfs(1, 1, 20000, 1);
for (int i = 1; i <= Q; ++i) cout << res[i] << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现