Recycle Rubbish 区间修改/赋值 线段树

大连海事大学第一届编程马拉松挑战赛多校联赛DIV1 第一场的1007,由于是private的比赛而且题目没有放出来,所以就不放题目连接了
题目大意就是一个数列实现区间值修改,区间值清零和区间查询,显然是线段树实现...
之前写的带Lazy标记的线段树只支持区间修改没有区间赋值,区间赋值跟修改还不太一样,相当于又打了一个标记,这个标记就是说:这个区间的值被清成了多少。
由于这道题的所有区间赋值都是清成0,所以打上标记为-1相当于区间赋值为0的标记,查询的之后和普通懒标记一样,先把标记下方然后继续查询。如果不是赋值为0标记那边换成一个结构体存赋成多少也是一样的。唯一的问题就是两种标记之间下放、查询的逻辑不能出错...一开始就这边没搞清楚WA了好几次.....

线段树还是不太熟,这种基础的东西还是要多练,争取能尽早搞出一个自己用的惯又优美的线段树模板。



#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;


typedef long long ll;
typedef pair<int, int> PII;
const int N = 100000+10;

#define lson step << 1
#define rson (step << 1) | 1
#define INF 0x3f3f3f3f

struct Node {
    int left,right;
    ll sum,lazy;
}L[N << 2];


void pushUp(int step)
{
    step >>= 1;
    while(step){
        L[step].sum = L[lson].sum + L[rson].sum;
        step = (step >> 1);
    }
}

void work(int step){
    L[lson].lazy = -1;
    L[rson].lazy = -1;
    L[lson].sum = 0;
    L[rson].sum = 0;
    L[step].lazy = 0;
}

void pushDown(int step)
{
    ll tmp = L[step].lazy;
    if(L[lson].lazy == -1 && L[lson].left != L[lson].right){
        work(lson);
    }
    if(L[rson].lazy == -1 && L[rson].left != L[rson].right){
        work(rson);
    }
    L[lson].lazy += tmp;
    L[rson].lazy += tmp;
    L[lson].sum += (L[lson].right - L[lson].left + 1) * tmp;
    L[rson].sum += (L[rson].right - L[rson].left + 1) * tmp;
    L[step].lazy = 0;
}

void init(int step,int l,int r)
{
    L[step].left = l;
    L[step].right = r;
    L[step].sum = 0;
    L[step].lazy = 0;
    if(l == r)
        return;
    int m = (l+r)>>1;
    init(lson, l ,m);
    init(rson, m+1, r);
}

ll querys(int step,int l,int r)
{
    if(l > r)return 0;
    if(L[step].lazy != 0){
        if(L[step].lazy == -1){
            L[lson].lazy = -1;
            L[rson].lazy = -1;
            L[lson].sum = 0;
            L[rson].sum = 0;
            L[step].lazy = 0;
        }
        else
        pushDown(step);
    }
    if(L[step].left == l && L[step].right == r){
        ll a = L[step].sum;
        return a;
    }
    int m = (L[step].left + L[step].right) >> 1;
    if( r < m ) {
        return querys(lson, l, r);
    }
    if( l > m ) {
        return querys(rson, l, r);
    }
    return querys(lson, l, m) + querys(rson, m+1, r);
}

void update(int step,int p,int w)
{
    if(L[step].left == L[step].right){
        L[step].sum = w;
        pushUp(step);
        return ;
    }
    int m = (L[step].left + L[step].right) >> 1;
    if(p <= m)update(lson, p, w);
    else update(rson, p, w);
}

void update(int step,int l,int r,ll w)
{
    if(l > r)return ;
    if(L[step].lazy != 0){
        if(L[step].lazy == -1){
            L[lson].lazy = -1;
            L[rson].lazy = -1;
            L[lson].sum = 0;
            L[rson].sum = 0;
            L[step].lazy = 0;
        }
        else{
            pushDown(step);
        }
    }
    if(L[step].left == l && L[step].right == r){
        L[step].lazy += w;
        L[step].sum += w * (r-l+1);
        pushUp(step);
        return;
    }
    int m = (L[step].left + L[step].right) >> 1;
    if( r < m ) {
        update(lson, l, r , w);
        return;
    }
    if( l > m ){
        update(rson, l, r , w);
        return;
    }
    update(lson, l, m , w);
    update(rson, m+1, r, w);
    
}

void update2(int step,int l,int r,int w)
{
    if(l > r)return ;
    if(L[step].lazy != 0){
        if(L[step].lazy == -1)return;
        pushDown(step);
    }
    if(L[step].left == l && L[step].right == r){
        L[step].lazy = -1;
        L[step].sum = 0;
        pushUp(step);
        return;
    }
    int m = (L[step].left + L[step].right) >> 1;
    if( r <= m ) {
        update2(lson, l, r , w);
        return;
    }
    if( l > m ){
        update2(rson, l, r , w);
        return;
    }
    update2(lson, l, m , w);
    update2(rson, m+1, r, w);
    
}

int n,Q;
char buf[100];
int main()
{
    while(~scanf("%d %d",&n,&Q)){
        init(1, 1, n);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            update(1, i, x);
        }
        for(int i=0;i<Q;i++){
            scanf("%s",buf);
            int l,r;
            scanf("%d%d",&l,&r);
            if(buf[0] == 'r'){
                ll ans = querys(1, l, r);
                update2(1, l, r, 0);
                printf("%lld\n",ans);
            }else{
                int w;
                scanf("%d",&w);
                update(1, l, r, w);
            }
        }
    }
    return 0;
}

/*
 5 4
 1 2 3 4 5
 r 1 5
 a 1 5 1
 r 5 5
*/


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值