社区讨论

线段树区间修改模板不知道哪错了,求助大佬

灌水区参与者 5已保存回复 12

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
12 条
当前快照
1 份
快照标识符
@lo9mghtn
此快照首次捕获于
2023/10/28 13:48
2 年前
此快照最后确认于
2023/10/28 13:48
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
#define ls(p) p<<1//zdy
#define rs(p) p<<1|1
const int maxn=100000;
int a[1000000];
struct  tree{
    int data;
}t[maxn*4];
int add[100000];//lazy数组
void build(int p,int l,int r) {
    if(l==r){
        t[p].data=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(ls(p),l,mid),build(rs(p),mid+1,r);
    t[p].data=t[p*2].data+t[p*2+1].data;
}
void ad(int k,int l,int r,int v){//加标记的函数
    add[k]+=v;//打标记
    t[k].data+=(r-l+1)*v;
}
void pushdown(int k,int l,int r,int mid){//当前节点,左端点,右端点,中端点
    if(add[k]==0) return //没有标记;
    ad(ls(k),l,mid,add[k]);
    ad(rs(k),mid+1,r,add[k]);//下传
    add[k]=0;//下传后,原标记删除;
}
void modify(int k,int l,int r,int x,int y,int v){//当前节点,当前递归左端点,右端点,需要添加的区间,以及需要添加的值
        if(l>=x&&r<=y) return ad(k,l,r,v);//递归到目标区间的子区间,不在向下递归,直接标记
        int mid=(l+r)>>1;
        pushdown(k,l,r,mid);
        if(x<=mid) modify(k*2,l,mid,x,y,v);//递归左子树
        if(mid<y) modify(k*2+1,mid+1,r,x,y,v);//递归右子树
        t[k].data=t[ls(k)].data+t[rs(k)].data;
        
}
int query(int k,int l,int r,int x,int y){//基本上与modify函数语句一样,只不过需要·1
    if(l>=x&&r<=y) return add[k];
    int mid=(l+r)>>1,res=0;
    pushdown(k,l,r,mid);//标记下传
    if(x<=mid) res+=query(k*2,l,mid,x,y);//递归左子树
    if(mid<y) res+=query(k*2+1,mid+1,r,x,y);//递归右子树
    return res;
} 
int  main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];  
    }
    build(1,1,n);
    while(m--){
        int op;
        cin>>op;
        if(op==1){
            int x,y,k;
            cin>>x>>y>>k;
            modify(1,1,n,x,y,k);
        }
        if(op==2){
            int x,y;
            cin>>x>>y;
            cout<<query(1,1,n,x,y)<<endl;
        }
    }
    return 0;

}

回复

12 条回复,欢迎继续交流。

正在加载回复...