P9334 [JOISC 2023] 水羊羹 2 题解
Description
给定一个长度为
Solution
首先注意到那些作为小段的区间一定长度为
考虑对于小段 dp,就得到一个单次
考虑挖掘大段的性质。
容易发现一个大段
但是根据上面的做法,大段要求之间只隔
不过可以证明只要选择的大段满足
所以求出以
由于
时间复杂度:
Code
#include <bits/stdc++.h> // #define int int64_t using i64 = int64_t; const int kMaxN = 2.5e5 + 5; int n, q, lim = 70; int a[kMaxN], f[kMaxN], g[kMaxN], ff[kMaxN], gg[kMaxN]; struct Node { int l, r; std::vector<std::pair<int, int>> vec; friend Node operator +(Node &a, Node &b) { if (a.r - a.l + 1 <= 0) return b; if (b.r - b.l + 1 <= 0) return a; static Node ret; assert(a.r == b.l - 1); ret.l = a.l, ret.r = b.r, ret.vec.clear(); for (int i = ret.l; i <= std::min(ret.l + lim, ret.r); ++i) { if (i <= a.r) { auto [p, c] = a.vec[i - a.l]; if (g[p + 2] <= b.r) ret.vec.emplace_back(b.vec[g[p + 2] - b.l].first, c + 1 + b.vec[g[p + 2] - b.l].second); else ret.vec.emplace_back(p, c); } else { ret.vec.emplace_back(b.vec[i - b.l]); } } return ret; } }; struct SGT { Node t[kMaxN * 4]; void pushup(int x) { t[x] = t[x << 1] + t[x << 1 | 1]; } void build(int x, int l, int r) { if (l == r) { t[x].l = t[x].r = l; t[x].vec = {{l, 0}}; return; } int mid = (l + r) >> 1; build(x << 1, l, mid), build(x << 1 | 1, mid + 1, r); pushup(x); } void update(int x, int l, int r, int ql, int qr) { if (l > qr || r < ql || l == r) return; int mid = (l + r) >> 1; update(x << 1, l, mid, ql, qr), update(x << 1 | 1, mid + 1, r, ql, qr); pushup(x); } Node query(int x, int l, int r, int ql, int qr) { if (l > qr || r < ql) return {0, -1, {}}; else if (l >= ql && r <= qr) return t[x]; int mid = (l + r) >> 1; Node ls = query(x << 1, l, mid, ql, qr), rs = query(x << 1 | 1, mid + 1, r, ql, qr); return ls + rs; } } sgt; struct BIT { i64 c[kMaxN]; void upd(int x, int v) { for (; x <= n; x += x & -x) c[x] += v; } i64 qry(int x) { i64 ret = 0; for (; x; x -= x & -x) ret += c[x]; return ret; } i64 qry(int l, int r) { return qry(r) - qry(l - 1); } } bit; void prework() { g[n + 1] = g[n + 2] = gg[n + 1] = gg[n + 2] = n + 1; for (int i = n; i; --i) { i64 sum = 0; f[i] = ff[i] = n + 1; for (int j = i; j <= n; ++j) { sum += a[j]; if (sum > a[j + 1] && ff[i] == n + 1) { ff[i] = j; } if (sum > a[i - 1] && sum > a[j + 1]) { f[i] = j; break; } } g[i] = std::min(g[i + 1], f[i]); } for (int i = 1; i <= n; ++i) { i64 sum = 0; gg[i] = 0; for (int j = i; j; --j) { sum += a[j]; if (sum > a[j - 1]) { gg[i] = j; break; } } } sgt.build(1, 1, n); } void rebuild(int x) { for (int i = std::min(x + 1, n); i >= std::max(x - lim, 1); --i) { i64 sum = 0; f[i] = ff[i] = n + 1; for (int j = i; j <= n; ++j) { sum += a[j]; if (sum > a[j + 1] && ff[i] == n + 1) { ff[i] = j; } if (sum > a[i - 1] && sum > a[j + 1]) { f[i] = j; break; } } g[i] = std::min(g[x + 2], f[i]); for (int j = i; j <= f[i] - 1; ++j) g[i] = std::min(g[i], f[j]); } sgt.update(1, 1, n, std::max(x - lim - 2, 1), std::min(x - 1, n - 2)); for (int i = x; i <= std::min(x + lim, n); ++i) { i64 sum = 0; gg[i] = 0; for (int j = i; j; --j) { sum += a[j]; if (sum > a[j - 1]) { gg[i] = j; break; } } } } int solve(int l, int r) { int ans1 = 1, ans2 = 0; if (bit.qry(l + 1, r) > a[l] || bit.qry(l, r - 1) > a[r]) ans2 = 2; if (ff[l] <= r) { int p = ff[l]; ans1 = 1; auto pp = sgt.query(1, 1, n, p, r); p = pp.vec[0].first, ans1 += 2 * pp.vec[0].second; if (p < r) { ++ans1; if (gg[r] > p + 1) ++ans1; } } if (g[l + 1] <= r) { int p = g[l + 1]; ans2 = 2; auto pp = sgt.query(1, 1, n, p, r); p = pp.vec[0].first, ans2 += 2 * pp.vec[0].second; if (p < r) { ++ans2; if (gg[r] > p + 1) ++ans2; } } return std::max(ans1, ans2); } void dickdreamer() { std::cin >> n; for (int i = 1; i <= n; ++i) { std::cin >> a[i]; bit.upd(i, a[i]); } prework(); std::cin >> q; for (int i = 1; i <= q; ++i) { int x, y, l, r; std::cin >> x >> y >> l >> r; bit.upd(x, y - a[x]); a[x] = y; rebuild(x); std::cout << solve(l + 1, r) << '\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 加持,快人一步
2024-02-14 LOJ #2876. 「JOISC 2014 Day2」水壶 题解