Miss_SGT @ 2023-01-22 19:50:19
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+5;
struct tree{
int l,r;
ll date,ad;
}t[4*maxn];
ll a[maxn],f;
int n,m;
int op,p,q;
void b(int x,int y,int s){
t[s].l=x;
t[s].r=y;
if(x==y){
t[s].date=a[x];
return;
}
int mid=(x+y)>>1;
b(x,mid,2*s);
b(mid+1,y,2*s+1);
t[s].date=t[s*2].date+t[s*2+1].date;
return;
}//建树
void bj(int s){
if(t[s].ad){
t[s].date+=t[s].ad*(t[s].r-t[s].l+1);
t[s*2].ad+=t[s].ad;
t[s*2+1].ad+=t[s].ad;
t[s].ad=0;
}
return;
}//标记下移
void add(int x,int y,int s,ll k){
if(x<=t[s].l&&t[s].r<=y){
t[s].date+=(k*(t[s].r-t[s].l+1));
t[s].ad+=k;
return;
}
bj(s);
int mid=(t[s].l+t[s].r)>>1;
if(x<=mid) add(x,mid,s*2,k);
if(y>mid) add(mid+1,y,s*2+1,k);
t[s].date=t[s*2].date+t[s*2+1].date;
return;
}
ll get(int x,int y,int s){
bj(s);
if(x<=t[s].l&&t[s].r<=y) return t[s].date;
int mid=(t[s].l+t[s].r)>>1;
ll ans=0;
if(x<=mid) ans+=get(x,mid,s*2);
if(mid<y) ans+=get(mid+1,y,s*2+1);
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
b(1,n,1);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op,&q,&p);
if(op==1){
scanf("%lld",&f);
add(q,p,1,f);
}else printf("%lld\n",get(q,p,1));
}
return 0;
}
by Miss_SGT @ 2023-01-22 19:51:33
按照题解写的,全wa,get里面那个标记我写在if前面,题解是后面(我觉得是前面)
by Michaellg @ 2023-01-22 20:28:27
@zhouchenqiao1 标记下传时不更新本节点的值,而是更新子节点的值,这样 get
的顺序就无所谓了。
另附我的下传标记的代码
inline void maketag(int nd, int len, ll num) {
xds[nd].tag += num;
xds[nd].num += len * num;
}
inline void pushdown(int nd, Range node) {
int mid = mymid(node);
maketag(lc(nd), mid - node.L + 1, xds[nd].tag);
maketag(rc(nd), node.R - mid, xds[nd].tag);
xds[nd].tag = 0;
}
by Miss_SGT @ 2023-01-23 13:07:21
@Michaellg 看懂了,谢谢
by Masterwei @ 2023-01-24 12:25:30
写分块不香吗