线段树板子求助
  • 板块灌水区
  • 楼主OneLeft
  • 当前回复16
  • 已保存回复16
  • 发布时间2023/8/5 18:54
  • 上次更新2023/11/3 05:42:15
查看原帖
线段树板子求助
574215
OneLeft楼主2023/8/5 18:54

rt,过不了样例/kk

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,u,x,y,z;
long long a[N],tree[4*N],lazy[4*N];
void push_up(int id)
{
    tree[id]=tree[id*2]+tree[id*2+1];
} //从子节点更新父节点
void push_down(int id,int l,int r) //从父节点更新子节点
{
    if(lazy[id]==0)return;
    int mid=(l+r)/2;
    lazy[id*2]+=lazy[id],lazy[id*2+1]+=lazy[id]; //更新两个子节点的懒标记
    tree[id*2]+=lazy[id]*(mid-l+1),tree[id*2+1]+=lazy[id]*(r-mid); //更新两个字节点的总和
    lazy[id]=0; //父节点的懒标记清零
}
void build(int id,int l,int r) //建线段树
{
    if(l==r)tree[id]=a[l];
    else
    {
        int mid=(l+r)/2;
        build(id*2,l,mid),build(id*2+1,mid+1,r); //建左子树和右子树
        push_up(id);
    }
}
long long query(int id,int l,int r,int x,int y) //区间求和
{
    if(l>=x&&r<=y)
    {
        if(lazy[id]!=0)tree[id]+=lazy[id],lazy[id]=0; //顺便更新懒标记
        return tree[id];
    }
    push_down(id,l,r); //查询前顺便更新懒标记
    int mid=(l+r)/2,res=0;
    if(x<=mid)res+=query(id*2,l,mid,x,y);
    if(y>mid)res+=query(id*2+1,mid+1,r,x,y);
    return res;
}
void updata(int id,int l,int r,int x,int y,long long z) //区间更新
{
    if(l>=x&&r<=y)tree[id]+=z*(r-l+1),lazy[id]+=z; //添加懒标记
    else
    {
        push_down(id,l,r); //顺便更新懒标记
        int mid=(l+r)/2;
        if(x<=mid)updata(id*2,l,mid,x,y,z);
        if(y>=mid)updata(id*2+1,mid+1,r,x,y,z);
        push_up(id); //更新父节点
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    build(1,1,n); //建线段树
    for(int i=1;i<=m;i++)
    {
        cin>>u>>x>>y;
        if(u==1)cin>>z,updata(1,1,n,x,y,z);
        else cout<<query(1,1,n,x,y)<<'\n';
    }
    return 0;
}
2023/8/5 18:54
加载中...