[线段树][简单复杂度分析]LOJ#6029. 「雅礼集训 2017 Day1」市场
2017-10-14 08:12
459 查看
Description
要求支持区间整除一个正整数,区间加,区间询问最小值,区间求和。Solution
就是复杂度分析吧。。和以前一道区间开根号的题差不多吧。。
好菜啊。只会做水题了。。
#include <bits/stdc++.h> using namespace std; const int N = 101010; const long long INF = 1ll << 60; typedef long long ll; inline char get(void) { static char buf[100000], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, 100000, stdin); if (S == T) return EOF; } return *S++; } template<typename T> inline void read(T &x) { static char c; x = 0; int sgn = 0; for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1; for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0'; if (sgn) x = -x; } int a ; ll sum[N << 2], mx[N << 2], mn[N << 2], add[N << 2]; int n, q, opt, l, r, x; inline void PushDown(int o, int l, int r) { if (add[o]) { int mid = (l + r) >> 1; add[o << 1] += add[o]; add[o << 1 | 1] += add[o]; mx[o << 1] += add[o]; mx[o << 1 | 1] += add[o]; mn[o << 1] += add[o]; mn[o << 1 | 1] += add[o]; sum[o << 1] += add[o] * (mid + 1 - l); sum[o << 1 | 1] += add[o] * (r - mid); add[o] = 0; } } inline void PushUp(int o) { mx[o] = max(mx[o << 1], mx[o << 1 | 1]); mn[o] = min(mn[o << 1], mn[o << 1 | 1]); sum[o] = sum[o << 1] + sum[o << 1 | 1]; } inline ll Div(ll x, ll y) { return floor((double)x / y); } inline void Build(int o, int l, int r) { add[o] = 0; if (l == r) { sum[o] = mx[o] = mn[o] = a[l]; return; } int mid = (l + r) >> 1; Build(o << 1, l, mid); Build(o << 1 | 1, mid + 1, r); PushUp(o); } inline void Add(int o, int l, int r, int L, int R, int x) { if (l >= L && r <= R) { add[o] += x; mx[o] += x; mn[o] += x; sum[o] += x * (r - l + 1); return; } PushDown(o, l, r); int mid = (l + r) >> 1; if (L <= mid) Add(o << 1, l, mid, L, R, x); if (R > mid) Add(o << 1 | 1, mid + 1, r, L, R, x); PushUp(o); } inline void Div(int o, int l, int r, int L, int R, int d) { if (l >= L && r <= R && mx[o] - Div(mx[o], d) == mn[o] - Div(mn[o], d)) { ll D = Div(mx[o], d) - mx[o]; add[o] += D; mx[o] += D; mn[o] += D; sum[o] += D * (r - l + 1); return; } PushDown(o, l, r); int mid = (l + r) >> 1; if (L <= mid) Div(o << 1, l, mid, L, R, d); if (R > mid) Div(o << 1 | 1, mid + 1, r, L, R, d); PushUp(o); } inline ll Sum(int o, int l, int r, int L, int R) { if (l >= L && r <= R) return sum[o]; PushDown(o, l, r); int mid = (l + r) >> 1; ll res = 0; if (L <= mid) res += Sum(o << 1, l, mid, L, R); if (R > mid) res += Sum(o << 1 | 1, mid + 1, r, L, R); return res; } inline ll Min(int o, int l, int r, int L, int R) { if (l >= L && r <= R) return mn[o]; PushDown(o, l, r); int mid = (l + r) >> 1; ll res = INF; if (L <= mid) res = min(res, Min(o << 1, l, mid, L, R)); if (R > mid) res = min(res, Min(o << 1 | 1, mid + 1, r, L, R)); return res; } int main(void) { freopen("1.in", "r", stdin); read(n); read(q); for (int i = 1; i <= n; i++) read(a[i]); Build(1, 1, n); for (int i = 1; i <= q; i++) { read(opt); read(l); read(r); ++l; ++r; if (opt == 1) { read(x); Add(1, 1, n, l, r, x); } else if (opt == 2) { read(x); Div(1, 1, n, l, r, x); } else if (opt == 3) { printf("%lld\n", Min(1, 1, n, l, r)); } else { printf("%lld\n", Sum(1, 1, n, l, r)); } } return 0; }
相关文章推荐
- #6029. 「雅礼集训 2017 Day1」市场--线段树区间更新
- #6029. 【雅礼集训 2017 Day1】市场
- loj 6030「雅礼集训 2017 Day1」矩阵
- loj6029 「雅礼集训 2017 Day1」市场
- 【题解】【雅礼集训 2017 Day5】远行 LOJ 6038 LCT
- #6030. 【雅礼集训 2017 Day1】矩阵
- LOJ 6041 「雅礼集训 2017 Day7」事情的相似度
- LibreOJ#6030. 「雅礼集训 2017 Day1」矩阵
- [后缀自动机 阈值] LOJ#6031. 「雅礼集训 2017 Day1」字符串
- 「长乐集训 2017 Day1」区间 线段树
- 【LOJ 6041】「雅礼集训 2017 Day7」事情的相似度
- LOJ 6043 「雅礼集训 2017 Day7」蛐蛐国的修墙方案
- [ 后缀自动机 树上启发式合并 线段树 树状数组 ] [ 雅礼集训 2017 Day7 ] LOJ#6041
- loj 6043 雅礼集训 2017 Day7 蛐蛐国的修墙方案
- LOJ 6045. 「雅礼集训 2017 Day8」价(最大闭合子图)
- 「6月雅礼集训 2017 Day1」看无可看
- LOJ 6100 「2017 山东二轮集训 Day1」第一题
- loj6030 「雅礼集训 2017 Day1」矩阵
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
- LOJ.6062.[2017山东一轮集训]Pair(Hall定理 线段树)