[LOJ 6029]「雅礼集训 2017 Day1」市场 题解
这道题恶心之处在于区间向下取整。
这里给出两种思路:
区间覆盖做法
如果最大值和最小值向下取整后相等,则对此区间进行区间覆盖。
我考场写的是这个,但是码错了,加上习惯不好,
差值相等做法
注意到相邻两数的向下取整的差值不可能大于
稍微推广一下,我们得到:
这说明从整点来看,函数
如果区间内
考虑到向下取整在进行多次后必然使数值、区间差值趋于
#include <bits/stdc++.h> #define LL long long using namespace std; const LL N = 1e5 + 5; const LL inf = 1e18; LL n, m, a[N], op, l, r, d; struct node { LL l, r, len, mn, mx, sum, lz; } t[N * 25]; LL fl(LL x, LL y) { if (0 <= x) return x / y; return -((-x + y - 1) / y); } void add(LL pos, LL k) { t[pos].lz += k; t[pos].sum += k * t[pos].len; t[pos].mn += k, t[pos].mx += k; } void pushup(LL pos) { t[pos].mn = min(t[pos * 2].mn, t[pos * 2 + 1].mn); t[pos].mx = max(t[pos * 2].mx, t[pos * 2 + 1].mx); t[pos].sum = t[pos * 2].sum + t[pos * 2 + 1].sum; } void down(LL pos) { if (t[pos].lz != 0) { LL k = t[pos].lz, l = pos * 2, r = pos * 2 + 1; add(l, k), add(r, k); t[pos].lz = 0; } } void build(LL pos, LL l, LL r) { t[pos].l = l, t[pos].r = r, t[pos].len = (r - l + 1); if (l == r) { t[pos].mx = t[pos].mn = t[pos].sum = a[l]; return; } LL mid = (l + r) / 2; build(pos * 2, l, mid), build(pos * 2 + 1, mid + 1, r); pushup(pos); } void upd1(LL pos, LL l, LL r, LL k) { if (t[pos].r < l || r < t[pos].l) return; if (l <= t[pos].l && t[pos].r <= r) { add(pos, k); return; } down(pos); upd1(pos * 2, l, r, k), upd1(pos * 2 + 1, l, r, k); pushup(pos); } void upd2(LL pos, LL l, LL r, LL k) { if (t[pos].r < l || r < t[pos].l) return; if (l <= t[pos].l && t[pos].r <= r && t[pos].l == t[pos].r) { t[pos].mn = t[pos].mx = t[pos].sum = fl(t[pos].sum, k); return; } down(pos); if (l <= t[pos].l && t[pos].r <= r && t[pos].mn - fl(t[pos].mn, k) == t[pos].mx - fl(t[pos].mx, k)) { add(pos, fl(t[pos].mx, k) - t[pos].mx); return; } upd2(pos * 2, l, r, k), upd2(pos * 2 + 1, l, r, k); pushup(pos); } LL querymn(LL pos, LL l, LL r) { if (t[pos].r < l || r < t[pos].l) return inf; if (l <= t[pos].l && t[pos].r <= r) return t[pos].mn; down(pos); return min(querymn(pos * 2, l, r), querymn(pos * 2 + 1, l, r)); } LL querysum(LL pos, LL l, LL r) { if (t[pos].r < l || r < t[pos].l) return 0; if (l <= t[pos].l && t[pos].r <= r) return t[pos].sum; down(pos); return querysum(pos * 2, l, r) + querysum(pos * 2 + 1, l, r); } int main() { scanf("%lld%lld", &n, &m); for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); } build(1, 1, n); for (int i = 1; i <= m; i++) { scanf("%lld", &op); if (op == 1) { scanf("%lld%lld%lld", &l, &r, &d); l++, r++; upd1(1, l, r, d); } if (op == 2) { scanf("%lld%lld%lld", &l, &r, &d); l++, r++; upd2(1, l, r, d); } if (op == 3) { scanf("%lld%lld", &l, &r); l++, r++; printf("%lld\n", querymn(1, l, r)); } if (op == 4) { scanf("%lld%lld", &l, &r); l++, r++; printf("%lld\n", querysum(1, l, r)); } } return 0; }
如果觉得不错的话,就给一个赞吧!
作者是 DengDuck ,转载请注明出处
文章链接: https://www.cnblogs.com/dengduck/p/17524182.html
感谢您阅读!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步