线段树代码0分RE求调,玄关

P3372 【模板】线段树 1

littlesnake @ 2024-01-31 21:46:54

rt.

#include <bits/stdc++.h>
#define maxn 100010
#define ll long long
ll a[maxn],w[maxn*4],lzy[maxn*4];
//更新区间和
void pushup(const int u){
    w[u]=w[u*2]+w[u*2+1];
}
//创建线段树
void build(const int u,int L,int R){
    if(L==R){
        w[u]=a[L];
        return ;
    }
    int M=(L+R)/2;
    build(u*2,L,M);
    build(u*2+1,M+1,R);
    pushup(u);
}
//单点查询
ll query1(int u,int L,int R,int p){
    if(L==R){
        return w[u];
    }else{
        int M=(L+R)/2;
        if(M>=p){
            return query1(u*2,L,M,p);
        }else{
            return query1(u*2+1,M+1,R,p);
        }
    }
}
//单点修改
void update1(int u,int L,int R,int p,ll x){
    if(L==R){
        w[u]=x;
    }else{
        int M=(L+R)/2;
        if(M>=p){
            update1(u*2,L,M,p,x);
        }else{
            update1(u*2+1,M+1,R,p,x);
        }
        pushup(u);
    }
}
//判断[L,R]是否被[l,r]包含
bool InRange(int L,int R,int l,int r){
    return (l<=L)&&(R<=r);
}
//判断[L,R]是否和[l,r]完全无交
bool OutofRange(int L,int R,int l,int r){
    return (L>r)||(R<l);
}
//修改延迟标记和区间和
void maketag(int u,int len,ll x){
    lzy[u]+=x;
    w[u]+=len*x;
}
//下放懒标记
void pushdown(int u,int L,int R){
    int M=(L+R)/2;
    maketag(u*2,M-L+1,lzy[u]);
    maketag(u*2+1,R-M,lzy[u]);
    lzy[u]=0;
}
//区间查询
ll query(int u,int L,int R,int l,int r){
    if(InRange(L,R,l,r)){
        return w[u];
    }else if(!OutofRange(L,R,l,r)){
        int M=(l+r)/2;
        pushdown(u,L,R);
        return query(u*2,L,M,l,r)+query(u*2+1,M+1,R,l,r);
    }else return 0;
}
//区间修改
void update(int u,int L,int R,int l,int r,ll x){
    if(InRange(L,R,l,r)){
        maketag(u,R-L+1,x);
    }else if(!OutofRange(L,R,l,r)){
        int M=(L+R)/2;
        pushdown(u,L,R);
        update(u*2,L,M,l,r,x);
        update(u*2+1,M+1,R,l,r,x);
        pushup(u);
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    build(1,1,n);
    for(int t=1;t<=m;t++){
        int op,x,y;
        ll k;
        scanf("%d",&op);
        if(op==1){
            scanf("%d %d %lld",&x,&y,&k);
            update(1,1,n,x,y,k);
        }else{
            scanf("%d %d",&x,&y);
            printf("%lld\n",query(1,1,n,x,y));
        }
    }
    return 0;
}

我可能写的函数有点多余,这是为了做模板哈。


by Exp10re @ 2024-01-31 22:00:19

@xsy2013

  1. 72 行的 int M=(l+r)/2; 改成 int M=(L+R)/2;

  2. 其实没有必要写这么多函数,很繁琐。建议参考 OI-Wiki 上的线段树模板,或者也可以参考我的代码。

  3. 线段树可爱捏。


by littlesnake @ 2024-01-31 22:05:39

@Exp10re 已关,感谢。


|