1 条题解
-
1
暴力做法不可行,考虑线段树。
有过线段树刷题的同学可能一眼就看出来是线段树板子题,就是一个区间修改和区间查询的模板。
注意这里卡掉了不加优化的线段树做法。
考虑 函数,它作用后 的值变化非常快,几乎几次就会变为个位数,我们发现当它成为个位数时 函数就没用了。
我们就需要加入一个优化,让我们修改的次数减少一些。即维护区间最大值,只要当前这个区间的最大值都小于 了,那么直接不修改这个区间的所有数直接返回。
所以线段树需要维护的值为:
- 最小值
- 最大值
- 的值
其他操作就和板子操作一样了。具体看提交代码细节。
ps:经过测试输入输出太多,不关闭同步流会跑 ,故而时限是
时间复杂度
#include <bits/stdc++.h> using u32 = unsigned; using i64 = long long; using u64 = unsigned long long; using i128 = __int128; constexpr i64 INF = 2e18; int f(i64 x) { int res = 0; while (x) { res += x % 10; x /= 10; } return res; } #define ls u << 1 #define rs u << 1 | 1 template<class Info> struct SegmentTree { int n; std::vector<Info> tr; SegmentTree(int _): n(_), tr(_ << 2) {} SegmentTree(std::vector<i64> a): SegmentTree(int(a.size() - 1)) { std::function<void(int, int, int)> build = [&](int u, int l, int r) -> void { if (l == r) { tr[u] = {l, r, 1, a[l], a[l], a[l]}; return; } tr[u] = {l, r}; int mid = (l + r) >> 1; build(ls, l, mid), build(rs, mid + 1, r); pushup(u); }; build(1, 1, n); } void apply(int u, int v) { tr[u].apply(v); } void pushup(int u) { tr[u] = tr[ls] + tr[rs]; } void modify(int u, int l, int r) { if (tr[u].l == tr[u].r) { apply(u, 0); return; } if (l <= tr[u].l && tr[u].r <= r && tr[u].max < 10) return; int mid = (tr[u].l + tr[u].r) >> 1; if (l <= mid) { modify(ls, l, r); } if (r > mid) { modify(rs, l, r); } pushup(u); } Info query(int u, int l, int r) { if (l <= tr[u].l && tr[u].r <= r) { return tr[u]; } if (r <= tr[ls].r) { return query(ls, l, r); } else if (l >= tr[rs].l) { return query(rs, l, r); } else { return query(ls, l, r) + query(rs, l, r); } } }; struct Info { int l, r, cnt; i64 min, max, v; void apply(int x) { v = f(v); min = max = v; } }; Info operator+(Info a, Info b){ Info res {}; res.l = a.l; res.r = b.r; res.cnt = a.cnt + b.cnt; res.min = std::min(a.min, b.min); res.max = std::max(a.max, b.max); return res; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n; std::cin >> n; std::vector<i64> a(n + 1); for (int i = 1; i <= n; i++) { std::cin >> a[i]; } SegmentTree<Info> seg(a); int m; std::cin >> m; while (m--) { int op, l, r; std::cin >> op >> l >> r; if (op == 1) { seg.modify(1, l, r); } else { std::cout << seg.query(1, l, r).min << '\n'; } } return 0; }
- 1
信息
- ID
- 52
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- 递交数
- 32
- 已通过
- 7
- 上传者