刚学的线段树求调RE

P3372 【模板】线段树 1

OIer_dcy__AK_IOI @ 2024-01-05 12:53:16

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
struct tree{ //树的结构体 
    int l,r,sum,add;
    /* l是当前节点覆盖区间的左端点
       r是右前节点覆盖区间的右端点
       sum是当前区间结点的和
       add是懒标记 
    */
}t[4*N]; //存树 
int n,q; //序列长度为n,查询次数q 
int a[N]; //a数组存序列 
//建树
inline void build(int pos,int l,int r){ //pos为当前节点下标,l为左端点,r为右端点 
    t[pos].l=l,t[pos].r=r; //当前节点的左端点为l,右端点为r 
    if(l==r){ //如果是叶子节点(区间长度为1) 
        t[pos].sum=a[l]; //当前区间的和为节点本身 
        return ;  //回溯 
    }else{
        int mid=(l+r)>>1; //取区间中点 
        int left=pos<<1; //左子树根节点的下标 
        int right=pos<<1|1; //右子树根节点的下标 
        build(left,1,mid); //递归遍历左子树(求左子树的最大值) 
        build(right,mid+1,r); //递归遍历右子树(求右子树的最大值) 
        t[pos].sum=t[left].sum+t[right].sum; //当前节点的最大值=左子树最大值+右子树最大值
    }
}
//向下继承(懒标记的向下更新) 
void pushdown(int pos){
    int left=pos<<1,right=pos<<1|1;
    auto &root= t[pos],&ll=t[left],&rr=t[right];
    if(root.add!=0){
        ll.add+=root.add;
        ll.sum+=(ll.r-ll.l+1)*root.add;
        rr.add+=root.add;
        rr.sum+=(rr.r-rr.l+1)*root.add;
        root.add=0;
    }
}
//区间修改 
inline void update2(int pos,int x,int y,int k){
    int l=t[pos].l,r=t[pos].r,mid=(l+1)>>1;
    if(x<=l&&y>=r){
        t[pos].sum+=(r-l+1)*k;
        t[pos].add+=k; //懒标记,子节点还没有更新,在下次查询以及区间修改时更新 
    }else{
        pushdown(pos);
        int left=pos<<1,right=pos<<1|1;
        if(x<=mid){
            update2(left,x,y,k);
        }
        if(y>=mid){
            update2(right,x,y,k);
        }
        t[pos].sum=t[left].sum+t[right].sum;
    }
}
//查询区间最大值 
inline int getmax(int pos,int x,int y){
    int l=t[pos].l,r=t[pos].r,mid=(l+r)>>1;
    if(x<=l&&y>=r){
        return t[pos].sum;
    }
    pushdown(pos);
    int ans=0,left=pos*2,right=pos*2+1;
    if(x<=mid){
        ans+=getmax(left,x,y);
    }
    if(y>mid){
        ans+=getmax(right,x,y);
    }
    return ans;
}
signed main(){
    //输入 
    scanf("%lld%lld",&n,&q);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    build(1,1,n); //建树 
    while(q--){ //q次查询(修改) 
        int op;
        scanf("%lld",&op);
        if(op==1){ //区间修改  
            int x,y,d;
            scanf("%lld%lld%lld",&x,&y,&d);
            update2(1,x,y,d);
        }else if(op==2){ //区间查询 
            int x,y;
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",getmax(1,x,y));
        }
    }
    return 0;
}

by XuYueming @ 2024-01-05 12:55:51

build(left,1,mid); //递归遍历左子树(求左子树的最大值)


by XuYueming @ 2024-01-05 12:56:40

ans+=


by XuYueming @ 2024-01-05 13:37:57

@kdy_c_dcy


by OIer_dcy__AK_IOI @ 2024-01-05 17:48:05

@XuYueming 谢大佬,orz!!orz


by OIer_dcy__AK_IOI @ 2024-01-05 17:49:46

不要看注释,注释是我别的题写的qaq


by OIer_dcy__AK_IOI @ 2024-01-05 17:51:16

我没有ans啊?


by XuYueming @ 2024-01-05 17:53:21

原来你 getmax 是求和啊 @kdy_c_dcy


by OIer_dcy__AK_IOI @ 2024-01-05 17:55:06

@XuYueming 对啊,我的代码是从求最大值复制过来的


|