511_Juruo_wyk @ 2024-10-13 10:34:41
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+5;
int a[N],tree[N<<2],lazy[N<<2],n,m,op,l,r,k;
void build(int i,int l,int r){
if(l==r){
tree[i]=a[l];
return;
}
int mid=l+r>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
tree[i]=tree[i<<1]+tree[i<<1|1];
}
void spread(int i,int x,int y){
int mid=l+r>>1;
lazy[i<<1]+=lazy[i];
tree[i<<1]+=lazy[i]*(mid-l+1);
lazy[i<<1|1]+=lazy[i];
tree[i<<1|1]+=lazy[i]*(r-mid);
lazy[i]=0;
}
void tag(int i,int l,int r,int x,int y,int v){
if(x<=l&&r<=y){
lazy[i]+=v;
tree[i]+=v*(r-l+1);
return;
}
spread(i,l,r);
int mid=l+r>>1;
if(x<=mid)tag(i<<1,l,mid,x,y,v);
if(y>mid)tag(i<<1|1,mid+1,r,x,y,v);
tree[i]=tree[i<<1]+tree[i<<1|1];
}
int ask(int i,int l,int r,int x,int y){
if(x<=l&&r<=y)return tree[i];
int mid=l+r>>1,ans=0;
spread(i,l,r);
if(x<=mid)ans+=ask(i<<1,l,mid,x,y);
if(y>mid)ans+=ask(i<<1|1,mid+1,r,x,y);
return ans;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
scanf("%lld",&op);
if(op==1){
scanf("%lld %lld %lld",&l,&r,&k);
tag(1,1,n,l,r,k);
}
else{
scanf("%lld %lld",&l,&r);
cout<<ask(1,1,n,l,r)<<'\n';
}
}
return 0;
}
顺便提供我下载的测试数据1
in:
8 10
640 591 141 307 942 58 775 133
2 1 5
2 3 8
2 3 6
2 5 8
2 4 8
1 4 8 60
2 1 6
2 5 8
1 3 7 15
1 2 6 86
out:
2621
2356
1448
1908
2215
2859
2148
by masonxiong @ 2024-10-13 10:41:26
@511_Juruo_wyk
《使用 %lld
读入 int
》
这会出问题的吧。
by masonxiong @ 2024-10-13 10:42:02
@511_Juruo_wyk
但其实真正的问题是,您的 spread
函数中传入的左端点是 x,y
而您用的是全局变量 l,r
。
by da_ke @ 2024-10-13 10:44:52
@511_Juruo_wyk
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+5;
int a[N],tree[N<<2],lazy[N<<2],n,m;
void build(int i,int l,int r)
{
if(l==r){
tree[i]=a[l];
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
tree[i]=tree[i<<1]+tree[i<<1|1];
}
void spread(int i,int l,int r){
int mid=(l+r)>>1;
lazy[i<<1]+=lazy[i];
tree[i<<1]+=lazy[i]*(mid-l+1);
lazy[i<<1|1]+=lazy[i];
tree[i<<1|1]+=lazy[i]*(r-mid);
lazy[i]=0;
}
void tag(int i,int l,int r,int x,int y,int v){
if(x<=l&&r<=y){
lazy[i]+=v;
tree[i]+=v*(r-l+1);
return;
}
spread(i,l,r);
int mid=(l+r)>>1;
if(x<=mid)tag(i<<1,l,mid,x,y,v);
if(y>mid)tag(i<<1|1,mid+1,r,x,y,v);
tree[i]=tree[i<<1]+tree[i<<1|1];
}
int ask(int i,int l,int r,int x,int y){
if(x<=l&&r<=y)return tree[i];
int mid=(l+r)>>1,ans=0;
spread(i,l,r);
if(x<=mid)ans+=ask(i<<1,l,mid,x,y);
if(y>mid)ans+=ask(i<<1|1,mid+1,r,x,y);
return ans;
}
signed main(){
int op,l,r,k;
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
scanf("%lld",&op);
if(op==1){
scanf("%lld %lld %lld",&l,&r,&k);
tag(1,1,n,l,r,k);
}
else{
scanf("%lld %lld",&l,&r);
cout<<ask(1,1,n,l,r)<<'\n';
}
}
return 0;
}
不要乱在外面定义变量,spread
变量冲突了。
by da_ke @ 2024-10-13 10:45:38
@511_Juruo_wyk 另外,那个 mid=l+r>>1
最好写成 mid=l+((r-l)>>1)
;
by 511_Juruo_wyk @ 2024-10-13 10:50:25
@masonxiong @da_ke 谢谢,懂了
但是 #define int long long
应该对于“%lld
读入 int
”和“l+r>>1
l+((r-l)>>1)
”没什么影响吧?
by da_ke @ 2024-10-13 10:53:29
@511_Juruo_wyk 也对,但是 l+r>>1
不如 (l+r)>>1
,因为 -Wall 报警告。
by masonxiong @ 2024-10-13 11:28:24
@511_Juruo_wyk
关于第一个问题,我先道个歉,我没看到上面的 #define int long long
(
关于第二个问题,改后可以防计算过程溢出,但是没必要。