線段樹 -- 區間修改 【下放懶人標記】
阿新 • • 發佈:2018-12-31
//分為區間覆蓋,區間加或減. 這裡只寫一種區間覆蓋(其他的照著改一下就可以了). 如果都有那就要是雙標記, 下一篇講 .
模板題
板子:
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);
}
}
}