P6109 [Ynoi2009] rprmq1 题解
Description
有一个
一次修改操作会给出
一次查询操作会给出
Solution
容易发现可以扫描线,但是直接做的话查询时需要维护任意一段时刻内的区间最大值,这显然是做不了的。
但是如果所有的查询
这可以启发我们进行类似猫树分治的做法,从浅到深枚举线段树的每一层,找到所有横跨当前层不同节点的询问放在当前层做,剩下的放到更深层做。
由于横跨当前层不同节点的询问
时间复杂度:
Code
#include <bits/stdc++.h> #define int int64_t const int kMaxN = 5e4 + 5, kMaxQ = 5e5 + 5; int n, m, q; int l1[kMaxQ], r1[kMaxQ], l2[kMaxQ], r2[kMaxQ], ans[kMaxQ]; bool vis[kMaxQ]; std::vector<std::tuple<int, int, int, int, int>> ud; std::vector<std::tuple<int, int, int>> qq[kMaxN], vec[kMaxN]; struct SGT { int maxa[kMaxN * 8], maxb[kMaxN * 8], tag1[kMaxN * 8], tag2[kMaxN * 8], tagr[kMaxN * 8]; void pushup(int x) { maxa[x] = std::max(maxa[x << 1], maxa[x << 1 | 1]); maxb[x] = std::max(maxb[x << 1], maxb[x << 1 | 1]); } void addtag(int x, int v1, int v2) { maxb[x] = std::max(maxb[x], maxa[x] + v2); tag2[x] = std::max(tag2[x], tag1[x] + v2); maxa[x] += v1, tag1[x] += v1; } void reset(int x) { addtag(x << 1, tag1[x], tag2[x]), addtag(x << 1 | 1, tag1[x], tag2[x]); maxb[x] = maxa[x], tagr[x] = 1; tag1[x] = tag2[x] = 0; } void pushdown(int x) { if (tagr[x]) { reset(x << 1), reset(x << 1 | 1); tagr[x] = 0; } if (tag1[x] || tag2[x]) { addtag(x << 1, tag1[x], tag2[x]), addtag(x << 1 | 1, tag1[x], tag2[x]); tag1[x] = tag2[x] = 0; } } void build(int x, int l, int r) { maxa[x] = maxb[x] = tag1[x] = tag2[x] = tagr[x] = 0; if (l == r) return; int mid = (l + r) >> 1; build(x << 1, l, mid), build(x << 1 | 1, mid + 1, r); } void update(int x, int l, int r, int ql, int qr, int v) { if (l > qr || r < ql) return; else if (l >= ql && r <= qr) return addtag(x, v, std::max<int>(v, 0)); pushdown(x); int mid = (l + r) >> 1; update(x << 1, l, mid, ql, qr, v), update(x << 1 | 1, mid + 1, r, ql, qr, v); pushup(x); } int query(int x, int l, int r, int ql, int qr) { if (l > qr || r < ql) return 0; else if (l >= ql && r <= qr) return maxb[x]; pushdown(x); int mid = (l + r) >> 1; return std::max(query(x << 1, l, mid, ql, qr), query(x << 1 | 1, mid + 1, r, ql, qr)); } } sgt; void solve(int d) { for (int i = 1; i <= n; ++i) vec[i].clear(), qq[i].clear(); for (auto [l1, r1, l2, r2, x] : ud) vec[l1].emplace_back(l2, r2, x), vec[r1 + 1].emplace_back(l2, r2, -x); for (int i = 1; i <= q; ++i) { if (!vis[i] && ((l1[i] >> d) != (r1[i] >> d) || !d)) { if (l1[i] != r1[i]) assert((l1[i] >> d) == (r1[i] >> d) - 1); qq[r1[i]].emplace_back(i, l2[i], r2[i]); } } sgt.build(1, 1, n); for (int i = 1; i <= n; ++i) { for (auto [l, r, v] : vec[i]) { if (v < 0) sgt.update(1, 1, n, l, r, v); } for (auto [l, r, v] : vec[i]) { if (v >= 0) sgt.update(1, 1, n, l, r, v); } if (i % (1 << d) == 0) sgt.reset(1); for (auto [id, l, r] : qq[i]) ans[id] = std::max(ans[id], sgt.query(1, 1, n, l, r)); } for (int i = 1; i <= n; ++i) vec[i].clear(), qq[i].clear(); for (auto [l1, r1, l2, r2, x] : ud) vec[r1].emplace_back(l2, r2, x), vec[l1 - 1].emplace_back(l2, r2, -x); for (int i = 1; i <= q; ++i) { if (!vis[i] && ((l1[i] >> d) != (r1[i] >> d) || !d)) { if (l1[i] != r1[i]) assert((l1[i] >> d) == (r1[i] >> d) - 1); vis[i] = 1; qq[l1[i]].emplace_back(i, l2[i], r2[i]); } } sgt.build(1, 1, n); for (int i = n; i; --i) { for (auto [l, r, v] : vec[i]) { if (v < 0) sgt.update(1, 1, n, l, r, v); } for (auto [l, r, v] : vec[i]) { if (v >= 0) sgt.update(1, 1, n, l, r, v); } if (i % (1 << d) == (1 << d) - 1) sgt.reset(1); for (auto [id, l, r] : qq[i]) ans[id] = std::max(ans[id], sgt.query(1, 1, n, l, r)); } } void dickdreamer() { std::cin >> n >> m >> q; for (int i = 1; i <= m; ++i) { int l1, l2, r1, r2, x; std::cin >> l1 >> l2 >> r1 >> r2 >> x; ud.emplace_back(l1, r1, l2, r2, x); } for (int i = 1; i <= q; ++i) std::cin >> l1[i] >> l2[i] >> r1[i] >> r2[i]; for (int i = std::__lg(n) + 1; ~i; --i) { solve(i); } for (int i = 1; i <= q; ++i) std::cout << ans[i] << '\n'; } int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; // std::cin >> T; while (T--) dickdreamer(); // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2023-08-16 CF932E Team Work 题解