GLESENA @ 2023-08-03 19:40:52
代码 :
#include<bits/stdc++.h>
using namespace std;
#define lc i<<1
#define rc i<<1|1
#define mid (l+r)/2
int inPut[100000+1];
struct tree{
int l,r,sum,lazytag;
}t[100000001];
void push_down(int i)
{
t[lc].lazytag+=t[i].lazytag;
t[rc].lazytag+=t[i].lazytag;
t[lc].sum+=t[i].lazytag*(t[lc].r-t[lc].l+1);
t[rc].sum+=t[i].lazytag*(t[rc].r-t[rc].l+1);
t[i].lazytag=0;
}
void build(int i,int l,int r)
{
t[i].l=l;t[i].r=r;
if(l==r)
{
t[i].sum=inPut[l];
return ;
}
build(lc,l,mid);
build(rc,mid+1,r);
t[i].sum=t[lc].sum+t[rc].sum;
}
int search(int i,int l,int r)
{
//cout<<t[i].l<<" "<<t[i].r<<' '<<l<<' '<<r<<'\n';
if(l<=t[i].l&&r>=t[i].r)
{
return t[i].sum+t[i].lazytag*(t[i].r-t[i].l+1);
}
if(l>=t[i].r||r<=t[i].l)
{
return 0;
}
int rtrn=0;
push_down(i);
if(l<=t[lc].r)
{
rtrn+=search(lc,l,r);
}
if(r>=t[rc].l)
{
rtrn+=search(rc,l,r);
}
return rtrn;
}
void add(int i,int l,int r,int k)
{
if(l<=t[i].l&&r>=t[i].r)
{
t[i].lazytag=k;
t[i].sum+=k*(t[i].r-t[i].l+1);
return ;
}
push_down(i);
if(l<=t[lc].r)
{
add(lc,l,r,k);
}
if(r>=t[rc].l)
{
add(rc,l,r,k);
}
t[i].sum=t[lc].sum+t[rc].sum;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&inPut[i]);
}
build(1,1,n);
int op,x,y,k;
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&x,&y,&k);
add(1,x,y,k);
}
if(op==2)
{
scanf("%d%d",&x,&y);
cout<<search(1,x,y)<<endl;
}
}
return 0;
}
求区间和时,位于区间边缘的数如果需要push_back到t[i].l==t[i].r,就无法被计算。
如 输入
8 1
1 1 1 1 1 1 1 1
2 4 6
输出
2
如下面横线下的3个1都应该被计算,结果应该为1+1+1=3。 但第4个1没有被计算,只计算了第5和第6个1,结果为输出了2。
_____
1 1 1 1 1 1 1 1
1 1 1 1|1 1 1 1
1 1|1 1|1 1|1 1
1|1|1|1|1|1|1|1
1 2 3 4 5 6 7 8
也就是说,search函数正确无法查询到长度为1的区间的值。
蒟蒻求助。
by _Fancy_ @ 2023-08-03 19:43:16
@GLESENA search不得先求一个mid再比较吗
by _Fancy_ @ 2023-08-03 19:46:03
@yutiti80
int rtrn=0;
int mid=t[i].l+t[i].r>>1;
push_down(i);
if(l<=mid)
{
rtrn+=search(lc,l,r);
}
if(r>=mid)
{
rtrn+=search(rc,l,r);
}
by NightTide @ 2023-08-03 19:48:19
@GLESENA 第二个 if 吧等于号去掉
by NightTide @ 2023-08-03 19:48:53
@GLESENA 最后两个 if 是和 mid 比