CurryNo_1 @ 2023-03-26 21:18:02
#include<iostream>
#include<algorithm>
#define lc 2*k
#define rc 2*k+1
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll n,m,a[N],x,y,z,q,sum;
struct node{
int l;
int r;
ll mx;
} tree[4*N];
void build(ll k,ll l,ll r)
{
tree[k].l=l;
tree[k].r=r;
if(l==r)
{
tree[k].mx=a[l];
return;
}
ll mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
tree[k].mx=tree[lc].mx+tree[rc].mx;//储存区间和
}
void add(ll k,ll l,ll r,ll v)
{
if(tree[k].l==tree[k].r)
{
tree[k].mx+=v;
return;
}
ll mid=(r+l)>>1;
if(l>mid) add(rc,l,r,v);//区间全部位于右子树
else if(r<=mid) add(lc,l,r,v);//区间全部位于左子树
else
{
add(lc,l,mid,v);
add(rc,mid+1,r,v);
}
tree[k].mx=tree[lc].mx+tree[rc].mx;//从底层回溯是改变父节点的值
return;
}
ll query(ll k,ll l,ll r)
{
ll res=0;
if(tree[k].l>=l && tree[k].r<=r)
{
return tree[k].mx;
}
ll mid=(tree[k].l+tree[k].r)>>1;
if(l>mid) res+=query(rc,l,r);
else if(r<=mid) res+=query(lc,l,r);
else
{
res+=query(lc,l,mid);
res+=query(rc,mid+1,r);
}
return res;
}
int main()
{
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 >> x;
if(x==1)//区间加操作
{
cin >> y >> z >> q;
add(1,y,z,q);
}
else if(x==2)//查询操作
{
cin >> y >> z;
cout << query(1,y,z) << endl;
}
}
return 0;
}
by zdl777 @ 2023-03-26 21:42:13
不只是细节问题啊。 qaq
首先线段树区间修改需要懒标记。
细节问题的话 update 里面
ll mid=(r+l)>>1;
改成
ll mid=(tree[k].l+tree[k].r)>>1;
by FstAutoMaton @ 2023-03-26 21:42:54
@CurryNo_1 你需要push_down函数
by CurryNo_1 @ 2023-03-26 21:49:46
@zdl777 一定需要懒标记吗
by CurryNo_1 @ 2023-03-26 21:50:40
@zdl777 一定需要懒标记吗
by CurryNo_1 @ 2023-03-26 21:54:06
@zdl777 ll=(l+r)>>1改完了70pts,最后三个点tle了,应该是没有懒标记
by CurryNo_1 @ 2023-03-26 21:54:20
@caoshurui ll=(l+r)>>1改完了70pts,最后三个点tle了,应该是没有懒标记
by zdl777 @ 2023-03-26 22:05:15
@CurryNo_1 没有懒标记复杂度有问题,我每次给你一个
by CurryNo_1 @ 2023-03-26 23:09:14
@zdl777 行,谢谢解答