不会q==1,0分,求调!
查看原帖
不会q==1,0分,求调!
806299
tyyxbx楼主2024/8/6 19:39
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long a[N],tree[N<<2],tag[N<<2];
long long ls(long long p){  //左儿子
    return p<<1;
}
long long rs(long long p){  //右儿子
    return p<<1|1;
}
void push_up(long long p){ //从下到上传递区间值
    tree[p]=tree[ls(p)]+tree[rs(p)];
}
void push_up1(long long p){ //从下到上传递区间值
    tree[p]=tree[ls(p)]*tree[rs(p)];
}
void build(long long p,long long pl,long long pr){  //建树,p为节点编号,它指向区间[pl,pr]
    tag[p]=0;   //Lazy-Tag标记
    if(pl==pr){ //最底层的叶子,赋值
        tree[p]=a[pl];
        return;
    }
    long long mid=(pl+pr)>>1;
    build(ls(p),pl,mid);  //左儿子
    build(rs(p),mid+1,pr); //右儿子
    push_up(p);  //从下往上传递区间值
}
void addtag(long long p,long long pl,long long pr,long long d){  //给节点p打tag标记,并更新tree
    tag[p]+=d;  //打上tag标记
    tree[p]+=d*(pr-pl+1); //计算新的tree
}
void push_down(long long p,long long pl,long long pr){ //不能覆盖时,把tag传给子树
    if(tag[p]){  //有tag标记,这是以前做区间修改时留下的
        long long mid=(pl+pr)>>1;
        addtag(ls(p),pl,mid,tag[p]);   //传给左子树
        addtag(rs(p),mid+1,pr,tag[p]);  //传给右子树
        tag[p]=0;  //p自己的tag被传走了,归0
    }
}
void update(long long L,long long R,long long p,long long pl,long long pr,long long d){  //区间修改:[L,R]中每个元素加d
    if(L<=pl&&pr<=R){  //完全覆盖,直接返回这个节点
        addtag(p,pl,pr,d);  //给节点p打tag标记,下一次区间修改到p时会用到
        return;
    }
    push_down(p,pl,pr);
    long long mid=(pl+pr)>>1;
    if(L<=mid) update(L,R,ls(p),pl,mid,d);
    if(R>mid) update(L,R,rs(p),mid+1,pr,d);
    push_up(p);
}
void update1(long long L,long long R,long long p,long long pl,long long pr,long long d){  //区间修改:[L,R]中每个元素乘d
    if(L<=pl&&pr<=R){  //完全覆盖,直接返回这个节点
        addtag(p,pl,pr,d);  //给节点p打tag标记,下一次区间修改到p时会用到
        return;
    }
    push_down(p,pl,pr);
    long long mid=(pl+pr)>>1;
    if(L<=mid) update1(L,R,ls(p),pl,mid,d);
    if(R>mid) update1(L,R,rs(p),mid+1,pr,d);
    push_up1(p);
}
long long query(long long L,long long R,long long p,long long pl,long long pr){
    if(L<=pl&&pr<=R) return tree[p];
    push_down(p,pl,pr); //push_down不加上,亲人两行泪 //不能覆盖,递归子树
    long long res=0;
    long long mid=(pl+pr)>>1;
    if(L<=mid) res+=query(L,R,ls(p),pl,mid);  //左子节点有重叠
    if(R>mid) res+=query(L,R,rs(p),mid+1,pr);  //右子节点有重叠
    return res;  
}
int main(){
    long long n,m,b;
    cin>>n>>m>>b;
    for(long long i=1;i<=n;i++) cin>>a[i];
    build(1,1,n); //建树
    while(m--){
        long long q,L,R,d;
        cin>>q;
        if(q==1){
            cin>>L>>R>>d;
            update1(L,R,1,1,n,d);
        }
        else if(q==2){
            cin>>L>>R>>d;
            update(L,R,1,1,n,d);
        }
        else{
            cin>>L>>R;
            cout<<query(L,R,1,1,n)%b<<endl;
        }
    }
    return 0;
}
2024/8/6 19:39
加载中...