P11217 【MX-S4-T1】「yyOI R2」youyou 的垃圾桶
P11217 【MX-S4-T1】「yyOI R2」youyou 的垃圾桶 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
实际上整理整理没什么难的。主要是考数据结构,完了时间复杂度
通过推公式,二分找出经过 k 轮(全部都使用),能把血量清零。然后 k - 1, 去找最后一轮实际上用多少,这里主要是求 sum 与 二分,所以可以使用线段树上二分,或者树状数组求和 + 二分。
附上测评结果:
树状数组: 记录详情 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
线段树(不卡常):记录详情 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
线段树(卡常):记录详情 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
树状数组 + 二分
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <ctime> using namespace std; typedef long long LL; const int N = 200010; LL n, m, w; LL tr[N], trs[N]; LL a[N]; LL read() { LL x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if(ch == '-' ) f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') x = x * 10 + ch -'0', ch = getchar(); return x * f; } int lowbit(int x) { return x & -x; } void add(LL tr[], int x, LL k) { for (int i = x; i <= n; i += lowbit(i)) tr[i] += k; } void addd(int l, int r, LL k) { add(tr, l, k); add(tr, r + 1, -k); add(trs, l, l * k); add(trs, r + 1, -(r + 1) * k); } LL sum(LL tr[], int x) { LL res = 0; for (int i = x; i; i -= lowbit(i)) res += tr[i]; return res; } LL ssum(int x) { LL a = sum(tr, x), b = sum(trs, x); return (__int128)a * (x + 1) - b; } LL find(LL x, LL sum) { LL l = 0, r = 61; while (l < r) { LL mid = l + r >> 1; if ((__int128)sum * ((1ll << mid) - 1) >= x) r = mid; else l = mid + 1; } return l; } LL find2(LL w, LL k) { int l = 0, r = n; while (l < r) { int mid = l + r >> 1; if ((__int128)ssum(mid) * (1ll << k) >= w) r = mid; else l = mid + 1; } return l; } int main() { // freopen("wxyt4.in", "r", stdin); // freopen("wxyt4.out", "w", stdout); cin >> n >> m >> w; for (int i = 1; i <= n; i ++ ) { a[i] = read(); add(tr, i, a[i] - a[i - 1]); add(trs, i, 1ll * i * (a[i] - a[i - 1])); } LL last = ssum(n); while (m -- ) { LL l, r, d; l = read(); r = read(); d = read(); addd(l, r, d); last += (r - l + 1) * d; LL res = last, ans = 0; LL k = find(w, res) - 1; ans = k * n; ans += find2(w - res * ((1ll << k) - 1), k) - 1; printf("%lld\n", ans); } return 0; }
线段树上二分
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <ctime> using namespace std; typedef long long LL; const int N = 200010; LL n, m, w; LL a[N]; struct Node { int l, r; __int128 sum, add; }tr[N * 4]; LL read() { LL x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if(ch == '-' ) f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') x = x * 10 + ch -'0', ch = getchar(); return x * f; } void pushup(Node &u, Node &l, Node &r) { u = {l.l, r.r, l.sum + r.sum}; } void pushup(int u) { pushup(tr[u], tr[u << 1], tr[u << 1 | 1]); } void pushdown(Node &u, LL add) { u.sum += (u.r - u.l + 1) * add; u.add += add; } void pushdown(int u) { pushdown(tr[u << 1], tr[u].add); pushdown(tr[u << 1 | 1], tr[u].add); tr[u].add = 0; } void build(int u, int l, int r) { if (l == r) tr[u] = {l, r, a[l]}; else { tr[u] = {l, r}; int mid = l + r >> 1; build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); pushup(u); } } void modify(int u, int l, int r, int add) { if (l <= tr[u].l && tr[u].r <= r) pushdown(tr[u], add); else { pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if (l <= mid) modify(u << 1, l, r, add); if (r > mid) modify(u << 1 | 1, l, r, add); pushup(u); } } LL query(int u, int l, int r) { if (l <= tr[u].l && tr[u].r <= r) return tr[u].sum; else { pushdown(u); int mid = tr[u].l + tr[u].r >> 1; LL sum = 0; if (l <= mid) sum += query(u << 1, l, r); if (r > mid) sum += query(u << 1 | 1, l, r); return sum; } } LL findl(int u, int l, int r, LL k, LL w, LL sum) { if (tr[u].l == tr[u].r) { if ((__int128)(tr[u].sum + sum) * k < w) return -1; return tr[u].l; } else if (l <= tr[u].l && tr[u].r <= r) { pushdown(u); if ((__int128)(tr[u << 1].sum + sum) * k >= w) return findl(u << 1, l, r, k, w, sum); else return findl(u << 1 | 1, l, r, k, w, sum + tr[u << 1].sum); } } LL find(LL x, LL sum) { LL l = 0, r = 61; while (l < r) { LL mid = l + r >> 1; if ((__int128)sum * ((1ll << mid) - 1) >= x) r = mid; else l = mid + 1; } return l; } signed main() { // freopen("wxyt4.in", "r", stdin); // freopen("wxyt4.out", "w", stdout); cin >> n >> m >> w; for (int i = 1; i <= n; i ++ ) { a[i] = read(); } build(1, 1, n); LL last = query(1, 1, n); while (m -- ) { LL l, r, d; l = read(); r = read(); d = read(); modify(1, l, r, d); last += 1ll * (r - l + 1) * d; LL res = last, ans = 0; LL k = find(w, res) - 1; ans = k * n; ans += findl(1, 1, n, (1ll << k), w - res * ((1ll << k) - 1), 0) - 1; printf("%lld\n", ans); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2023-11-10 P1072 [NOIP2009 提高组] Hankson 的趣味题