「LOJ 6308」「雅礼国庆 2017 Day1」Mod
2018-03-28 21:25
281 查看
LOJ传送门
这道题居然让我想到了 jury_2 的集训队论文,其实确实还是有异曲同工之妙的。
对于操作 1,直接 Query 查询区间和;
对于操作 2,假设当前为区间为 [l,r],若 max{Ai|i∈[l,r]}<x,则直接返回,否则分别递归到左右儿子 [l,mid][mid+1,r],直到 l=r,对 x 取模后返回,更新区间;
对于操作 3,直接 Updata 单点修改。
复杂度为 O((m+n)lognlogw),w 为权值。
接着是操作 2,分析一下取模的性质:i mod x<i2,这个性质很显然。
于是对于数 ai,我们最多将其修改 O(logai) 次,每次修改为 O(logn)。
由于原数列有 n 个数以及操作 3 至多增加 m 个数,所以总的复杂度为 O((m+n)lognlogw)。
总的来说这还是一道不错的套路题。
这道题居然让我想到了 jury_2 的集训队论文,其实确实还是有异曲同工之妙的。
Solution
用线段树维护区间和以及区间最大值。对于操作 1,直接 Query 查询区间和;
对于操作 2,假设当前为区间为 [l,r],若 max{Ai|i∈[l,r]}<x,则直接返回,否则分别递归到左右儿子 [l,mid][mid+1,r],直到 l=r,对 x 取模后返回,更新区间;
对于操作 3,直接 Updata 单点修改。
复杂度为 O((m+n)lognlogw),w 为权值。
Proof
首先是操作 1,3,显然 O(mlogn);接着是操作 2,分析一下取模的性质:i mod x<i2,这个性质很显然。
于是对于数 ai,我们最多将其修改 O(logai) 次,每次修改为 O(logn)。
由于原数列有 n 个数以及操作 3 至多增加 m 个数,所以总的复杂度为 O((m+n)lognlogw)。
总的来说这还是一道不错的套路题。
#include <cstdio> #define Max(_A, _B) (_A > _B ? _A : _B) #define R register const int MaxN = 100010; int a[MaxN], B[1 << 18]; long long S[1 << 18]; void Build(R int node, R int begin, R int end) { if(begin == end) { S[node] = B[node] = a[begin]; return ; } R int mid = begin + end >> 1; Build(node << 1, begin, mid); Build(node << 1 | 1, mid + 1, end); S[node] = S[node << 1] + S[node << 1 | 1]; B[node] = Max(B[node << 1], B[node << 1 | 1]); } long long Query(R int node, R int begin, R int end, R int l, R int r) { if(l <= begin && end <= r) return S[node]; R int mid = begin + end >> 1; R long long t1 = 0, t2 = 0; if(l <= mid) t1 = Query(node << 1, begin, mid, l, r); if(r > mid) t2 = Query(node << 1 | 1, mid + 1, end, l, r); return t1 + t2; } void Updata(R int node, R int begin, R int end, R int pos, R int val) { if(begin == end) { S[node] = B[node] = val; return ; } R int mid = begin + end >> 1; if(pos <= mid) Updata(node << 1, begin, mid, pos, val); else Updata(node << 1 | 1, mid + 1, end, pos, val); S[node] = S[node << 1] + S[node << 1 | 1]; B[node] = Max(B[node << 1], B[node << 1 | 1]); } void Modify(R int node, R int begin, R int end, R int l, R int r, R int val) { if(B[node] < val) return ; if(l <= begin && end <= r) { if(begin == end) S[node] = B[node] = S[node] % val; else { R int mid = begin + end >> 1; if(B[node << 1] >= val) Modify(node << 1, begin, mid, l, r, val); if(B[node << 1 | 1] >= val) Modify(node << 1 | 1, mid + 1, end, l, r, val); S[node] = S[node << 1] + S[node << 1 | 1]; B[node] = Max(B[node << 1], B[node << 1 | 1]); } return ; } R int mid = begin + end >> 1; if(l <= mid) Modify(node << 1, begin, mid, l, r, val); if(r > mid) Modify(node << 1 | 1, mid + 1, end, l, r, val); S[node] = S[node << 1] + S[node << 1 | 1]; B[node] = Max(B[node << 1], B[node << 1 | 1]); } int main() { R int n, m; scanf("%d %d", &n, &m); for(R int i = 1; i <= n; i++) scanf("%d", &a[i]); Build(1, 1, n); while(m--) { R int opt; scanf("%d", &opt); if(opt == 1) { R int l, r; scanf("%d %d", &l, &r); printf("%lld\n", Query(1, 1, n, l, r)); } if(opt == 2) { R int l, r, x; scanf("%d %d %d", &l, &r, &x); Modify(1, 1, n, l, r, x); } if(opt == 3) { R int k, x; scanf("%d %d", &k, &x); Updata(1, 1, n, k, x); } } return 0; }
相关文章推荐
- [线段树][简单复杂度分析]LOJ#6029. 「雅礼集训 2017 Day1」市场
- loj 6030「雅礼集训 2017 Day1」矩阵
- LOJ 6045. 「雅礼集训 2017 Day8」价(最大闭合子图)
- 「6月雅礼集训 2017 Day1」看无可看
- LOJ 6100 「2017 山东二轮集训 Day1」第一题
- loj 6043 雅礼集训 2017 Day7 蛐蛐国的修墙方案
- 2017国庆 雅礼集训 题解合集
- loj6029 「雅礼集训 2017 Day1」市场
- LOJ 6041 「雅礼集训 2017 Day7」事情的相似度
- 【题解】【雅礼集训 2017 Day5】远行 LOJ 6038 LCT
- 2017北京国庆刷题Day1 morning
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
- 2017国庆郑州集训Day1
- 2017北京国庆刷题Day1 afternoon
- 【2017国庆雅礼集训划水记】 day1 四边形不等式
- 2017国庆郑州集训Day1
- [后缀自动机 阈值] LOJ#6031. 「雅礼集训 2017 Day1」字符串
- 学大伟业 2017 国庆 Day1
- [后缀自动机][阈值] LOJ #6031. 「雅礼集训 2017 Day1」字符串
- loj6030 「雅礼集训 2017 Day1」矩阵