Codefroces 438D. The Child and Sequence(线段树)
2017-03-27 19:57
363 查看
题目链接:http://codeforces.com/contest/438/problem/D
昨晚,吉如一老师做客51Nod给我们讲解了线段树lazy标记的应用,其中,这是最简单的那道题(???)。
这道题目,如果是想完全暴力修改一个区间取模的话,显然是不行的,复杂度太高。这时候,jls教我们用lazy标记去做这道题。
首先,我们有一个结论,有一个数字x,对p取模,如果x < p,那么x显然是不会改变的。如果x >= p,那么,x会改变。
拓展开来,可以得到,如果x对p1取模(x >= p1),然后再对p2取模(p2 > p1),那么这个x肯定是不会再更新了的。(例如3%2=1,然后1%3=1)
所以我们的懒惰标记就用在这个地方了,我们不断维护一个区间的最大模数p,如果判断到输入的模数mod > p,那么就可以直接return不用再更新下面的区间。
这并不是一道lazy标记的典型应用,我们也不需要pushdown这种操作,但他确实减少了修改的常数从而降低复杂度。
靠着jls推荐的模板,我写了一发,调了很久终于过了
- -其他博客上x%p<=x/2(x>=p)到底是什么鬼啊,我根本没用上也不知道怎么用。
代码如下:
昨晚,吉如一老师做客51Nod给我们讲解了线段树lazy标记的应用,其中,这是最简单的那道题(???)。
这道题目,如果是想完全暴力修改一个区间取模的话,显然是不行的,复杂度太高。这时候,jls教我们用lazy标记去做这道题。
首先,我们有一个结论,有一个数字x,对p取模,如果x < p,那么x显然是不会改变的。如果x >= p,那么,x会改变。
拓展开来,可以得到,如果x对p1取模(x >= p1),然后再对p2取模(p2 > p1),那么这个x肯定是不会再更新了的。(例如3%2=1,然后1%3=1)
所以我们的懒惰标记就用在这个地方了,我们不断维护一个区间的最大模数p,如果判断到输入的模数mod > p,那么就可以直接return不用再更新下面的区间。
这并不是一道lazy标记的典型应用,我们也不需要pushdown这种操作,但他确实减少了修改的常数从而降低复杂度。
靠着jls推荐的模板,我写了一发,调了很久终于过了
- -其他博客上x%p<=x/2(x>=p)到底是什么鬼啊,我根本没用上也不知道怎么用。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int Maxn = 100000 + 5; long long a[Maxn]; inline long long unique_input() { bool p = 0; char ch = getchar(); while((ch < '0' || ch > '9') && ch != '-') ch = getchar(); if(ch == '-') { ch = getchar(); p = true; } long long ans = 0; while(ch >= '0' && ch <= '9') { ans = ans * 10 + ch - '0'; ch = getchar(); } return p ? -ans : ans; } struct seg { int l, r; long long val, Max; }segtree[Maxn * 4]; void build(int node, int l, int r) { segtree[node].l = l; segtree[node].r = r; if(l == r) { segtree[node].val = unique_input(); segtree[node].Max = segtree[node].val; return; } else { int mid = (l + r) >> 1; int tl = node << 1, tr = node << 1 | 1; build(tl, l, mid); build(tr, mid + 1, r); segtree[node].Max = max(segtree[tl].Max, segtree.Max); segtree[node].val = segtree[tl].val + segtree .val; } } long long query(int node, int ql, int qr) { if(segtree[node].r < ql || segtree[node].l > qr)//递归进来才判断是否剪枝 return 0; if(segtree[node].l >= ql && segtree[node].r <= qr) return segtree[node].val; int mid = segtree[node].l + segtree[node].r >> 1; long long res = 0; int tl = node << 1, tr = node << 1 | 1; res += query(tl, 4000 ql, qr); res += query(tr, ql, qr); return res; } void Maintain(int node) { segtree[node].val = segtree[node<<1].val + segtree[node<<1|1].val; segtree[node].Max = max(segtree[node<<1].Max, segtree[node<<1|1].Max); } bool Cut(int node) { return 0; } bool check(int node, int mod) { if(segtree[node].Max < mod) return 1; return 0; } void update_lr(int node, int ql, int qr, long long mod) { if(segtree[node].r < ql || segtree[node].l > qr || Cut(node))//递归进来才判断是否剪枝 return; if(segtree[node].l >= ql && segtree[node].r <= qr && check(node, mod)) return; if(segtree[node].l == segtree[node].r) { segtree[node].val %= mod; segtree[node].Max = segtree[node].val; return; } int mid = segtree[node].l + segtree[node].r >> 1; update_lr(node << 1, ql, qr, mod);//无脑递归 update_lr(node << 1 | 1, ql, qr, mod); Maintain(node); } void update_point(int node, int x, long long val) { if(segtree[node].r < x || segtree[node].l > x)//递归进来才判断是否剪枝 return; if(segtree[node].l == x && segtree[node].l == segtree[node].r) { segtree[node].val = val; segtree[node].Max = val; return; } int tl = node << 1, tr = node << 1 | 1; update_point(tl, x, val); update_point(tr, x, val); segtree[node].val = segtree[tl].val + segtree .val; segtree[node].Max = max(segtree[tl].Max, segtree .Max); } int main() { int n, m, i, ope; int l, r; long long val; scanf("%d%d", &n, &m); build(1, 1, n); while(m--) { scanf("%d", &ope); if(ope == 1) { l = unique_input(); r = unique_input(); printf("%I64d\n", query(1, l, r)); } else if(ope == 2) { l = unique_input(); r = unique_input(); val = unique_input(); update_lr(1, l, r, val); } else { l = unique_input(); val = unique_input(); update_point(1, l, val); } } return 0; } 相关文章推荐
- [均摊复杂度线段树]Codeforces 438D. The Child and Sequence
- codeforces 438D. The Child and Sequence(线段树)
- CF(438D) The Child and Sequence(线段树)
- CF(438D) The Child and Sequence(线段树)
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树
- Codeforces Round #250 (Div. 1) D. The Child and Sequence(线段树暴力)
- codeforces438 D The Child and Sequence
- The Child and Sequence(线段树)
- Codeforces Round #250 (Div. 1) D. The Child and Sequence (线段树)
- 438D - The Child and Sequence
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模
- 有趣的线段树小集合 Codeforces Round #250 (Div. 1) D. The Child and Sequence
- Codeforce 438D-The Child and Sequence
- 【Codeforces 438 D】The Child and Sequence
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸
- 线段树【CF620E】The Child and Sequence
- [均摊 平衡树 || 线段树] Codeforces 438D #250 (Div. 1) D. The Child and Sequence
- The Child and Sequence
- CodeForces 438 E.The Child and Binary Tree(生成函数+FFT)
- Codeforces Round #250 (Div. 1) D. The Child and Sequence