1. 程式人生 > >線段樹 -- 區間修改 【下放懶人標記】

線段樹 -- 區間修改 【下放懶人標記】

//分為區間覆蓋,區間加或減. 這裡只寫一種區間覆蓋(其他的照著改一下就可以了). 如果都有那就要是雙標記, 下一篇講 .

模板題
板子:

const int maxn = 1e5+5;
int a[maxn];
struct Tree {
    int tl, tr; ll val, lazy;
    void fun(ll tmp) {      //如果是加值是所有的 = 都用 +=. 下次不要被坑啦!
        lazy = tmp;
        val = (tr - tl + 1) * tmp;
    }
} tre[maxn<<2];
void pushup(int
id) { tre[id].val = tre[id<<1].val + tre[id<<1|1].val; } void pushdown(int id) { if(tre[id].lazy) { tre[id<<1].fun(tre[id].lazy); tre[id<<1|1].fun(tre[id].lazy); tre[id].lazy = 0; } } void build(int id,int l,int r) { tre[id].tl = l; tre[id
].tr = r; tre[id].lazy = 0; if(l == r) { tre[id].val = 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 = tre[id].tl, r = tre[id].tr; if
(ul <= l && r <= ur) { tre[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 query(int id, int ql, int qr) { int l = tre[id].tl , r = tre[id].tr; if(ql <= l && r <= qr) { return tre[id].val; } pushdown(id); int mid = (l+r) >> 1 ; if(qr <= mid) return query(id<<1, ql, qr); else if(ql > mid) return query(id<<1|1, ql, qr); else return query(id<<1, ql, mid) + query(id<<1|1, mid+1, 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); printf("%lld\n", query(1, l, r)); } else{ scanf("%d%d%d", &l, &r, &w); update(1, l, r, w); } } }