您的位置:首页 > 其它

线段树 -- 区间修改 【下放懒人标记】

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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: