线段树 -- 区间修改 【下放懒人标记】
2017-07-26 15:50
281 查看
//分为区间覆盖,区间加或减. 这里只写一种区间覆盖(其他的照着改一下就可以了). 如果都有那就要是双标记, 下一篇讲 .
模板题
板子: (老规矩)
解释版
模板题
板子: (老规矩)
const int maxn = 1e5+5; int cas=1; int a[maxn]; struct node{ int tl, tr; ll val, maxx, lazy; void fun(ll tmp) { //如果是加值是所有的 = 都用 +=. 下次不要被坑啦! lazy = tmp; val = (tr - tl + 1) * tmp; maxx = tmp; } } tree[maxn*4]; void pushup(int id) { tree[id].val = tree[id<<1].val+tree[id<<1|1].val; tree[id].maxx = max(tree[id<<1].maxx,tree[id<<1|1].maxx); } void pushdown(int id) { if(tree[id].lazy){ tree[id<<1].fun(tree[id].lazy); tree[id<<1|1].fun(tree[id].lazy); tree[id].lazy = 0; } } void build(int id,int l,int r) { tree[id].tl = l; tree[id].tr = r; tree[id].lazy = 0; if(l == r){ tree[id].val = tree[id].maxx = a[l]; return ; } int mid = (l+r) >> 1; build(id<<1, l, mid); build(id<<1|1, mid+1, r); pushup(id); } void update(int id, int ul, int ur, int val) { int l = tree[id].tl, r = tree[id].tr; if(ul <= l && r <= ur){ tree[id].fun(val); return ; } pushdown(id); int mid = (l+r) >> 1; if(ul <= mid) update(id<<1, ul, ur, val); if(ur > mid) update(id<<1|1, ul, ur, val); pushup(id); } ll ans; void query(int id, int ql, int qr) { int l = tree[id].tl , r = tree[id].tr; if(ql <= l && r <= qr) { ans += tree[id].val; return ; } pushdown(id); int mid = (l+r) >> 1 ; if(ql <= mid) query(id<<1, ql, qr); if(qr > mid) query(id<<1|1, ql, qr); } void solve() { int n; scanf("%d",&n); for(int i = 1 ; i <= n ; i ++) { scanf("%d", &a[i]); } build(1, 1, n); int q; scanf("%d",&q); while(q--){ int op, l, r, w; scanf("%d%", &op); if(op == 0){ scanf("%d%d", &l, &r); ans = 0; query(1, l, r); printf("%lld\n", ans); } else{ scanf("%d%d%d", &l, &r, &w); update(1, l, r, w); } } }
解释版
/** @Cain*/ const int maxn = 1e5+5; int cas=1; int a[maxn]; struct node{ int tl, tr; ll val, maxx, lazy; void fun(ll tmp) { //如果是直接加值就用 += lazy = tmp; val = (tr - tl + 1) * tmp; maxx = tmp; } } tree[maxn*4]; void pushup(int id) { tree[id].val = tree[id<<1].val+tree[id<<1|1].val; tree[id].maxx = max(tree[id<<1].maxx,tree[id<<1|1].maxx); } void pushdown(int id) //下放懒人标记 { if(tree[id].lazy){ //这个区间有懒人标记时才用. tree[id<<1].fun(tree[id].lazy); tree[id<<1|1].fun(tree[id].lazy); tree[id].lazy = 0; //下放后记得清零 } } void build(int id,int l,int r) { tree[id].tl = l; tree[id].tr = r; tree[id].lazy = 0; if(l == r){ tree[id].val = tree[id].maxx = a[l]; return ; } int mid = (l+r) >> 1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); pushup(id); } void update(int id, int ul, int ur, int val) { int l = tree[id].tl, r = tree[id].tr; if(ul <= l && r <= ur){ tree[id].fun(val); return ; } pushdown(id); int mid = (l+r) >> 1; if(ul <= mid) update(id<<1, ul, ur, val); if(ur > mid) update(id<<1|1, ul, ur, val); pushup(id); } ll ans; void query(int id, int ql, int qr) { int l = tree[id].tl , r = tree[id].tr; if(ql <= l && r <= qr) { ans += tree[id].val; return ; } pushdown(id); //如果当前区间不是我们所需要的区间,就要访问下一个区间, 则就要下放懒人标记. int mid = (l+r) >> 1 ; if(ql <= mid) query(id<<1, ql, qr); if(qr > mid) query(id<<1|1, ql, qr); } void solve() { int n; scanf("%d",&n); for(int i = 1 ; i <= n ; i ++) { scanf("%d", &a[i]); } build(1, 1, n); int q; scanf("%d",&q); while(q--){ int op, l, r, w; scanf("%d%", &op); if(op == 0){ scanf("%d%d", &l, &r); ans = 0; query(1, l, r); printf("%lld\n", ans); } else{ scanf("%d%d%d", &l, &r, &w); update(1, l, r, w); } } }
相关文章推荐
- hiho一下 第二十周(线段树区间修改+延迟标记)
- 线段树区间修改之双标记 【lazy两重标记并且分类讨论】
- 【codevs1690】开关灯 线段树 区间修改+区间求和(标记)
- hihocoder1078线段树修改区间查询区间(懒标记)
- bzoj 1798 双标记区间修改线段树
- 线段树区间修改 lazy标记 大法
- 线段树 (区间修改 区间查询 延迟标记)
- 区间操作(线段树、树状数组、懒人标记、RMQ算法)
- hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)
- PKU 4047 - Garden(线段树 + 区间修改)
- 线段树模板(点修改 ,区间查询)
- [POJ 2104]K-th Number (不带修改的区间k大,函数式线段树)
- HDU 1166 敌兵布阵 【线段树-点修改--计算区间和】
- hihocoder#1078 线段树的区间修改
- 线段树区间修改与查询(求和)
- 【线段树--区间修改】poj3468
- poj2886线段树(单点修改,区间查询)
- POJ 3468 A Simple Problem with Integers(线段树区间修改)
- POJ 3468 线段树 区间修改 基础题
- HDU 1698 Just a Hook 线段树区间修改