问题描述
线段树可以快速得对一段区间做修改操作,时间复杂度为O(logN)
实现
在每个节点处增加一个lazyTag,当节点所在的区间都被修改时,将修改记录在lazyTag中,不用再往下递归。当查询或者下次修改到改节点时,将lazyTag下移。
#include <bits/stdc++.h>
using namespace std;
enum {maxn = 1<<17};
struct Node{
int all;
int lazyTag;
};
Node st[maxn<<1];
int p[maxn];
void pushDown(int rt, int L, int R)
{
if (st[rt].lazyTag && L!=R)
{
int m = L+(R-L)/2;
st[rt<<1].lazyTag = st[rt<<1|1].lazyTag = st[rt].lazyTag;
st[rt<<1].all = (m+1-L) * st[rt].lazyTag;
st[rt<<1|1].all = (R-m)* st[rt].lazyTag;
st[rt].lazyTag = 0;
}
}
void build(int rt, int L, int R)
{
st[rt].lazyTag = 0;
if (L==R)
{
st[rt].all = p[L];
}
else{
int m = L+(R-L)/2;
build(rt<<1, L, m);
build(rt<<1|1, m+1, R);
st[rt].all = st[rt<<1].all + st[rt<<1|1].all;
}
}
int ql, qr;
int q(int rt, int L, int R)
{
if (ql <= L && R <= qr)
return st[rt].all;
if (R < ql || qr<L)
return 0;
pushDown(rt, L, R);
int m = L+ (R-L)/2;
return q(rt<<1, L, m) + q(rt<<1|1, m+1, R);
}
int ul, ur, uv;
void update(int rt, int L, int R)
{
if (ul <= L && R <= ur)
{
st[rt].all = (R+1-L) * uv;
st[rt].lazyTag = uv;
return ;
}
if (R< ul || ur<L)
return;
pushDown(rt, L, R);
int m = L+(R-L)/2;
update(rt<<1, L, m);
update(rt<<1|1, m+1, R);
st[rt].all = st[rt<<1].all + st[rt<<1|1].all;
}
int main()
{
int n;
scanf("%d", &n);
for (int i=1; i<= n; i++)
{
scanf("%d", &p[i]);
}
build(1, 1, n);
int m;
scanf("%d", &m);
for (int i=0; i< m; i++)
{
int o;
scanf("%d", &o);
if (o)
{
scanf("%d %d %d", &ul, &ur, &uv);
update(1, 1, n);
}else{
scanf("%d %d", &ql, &qr);
printf("%d\n", q(1, 1, n));
}
}
return 0;
}