静态线段树(动态开点的后边再补
#include<cstdio> typedef long long ll; #define INT 100005 struct node{ ll data; ll l,r; ll lztag; } tr[INT*4]; ll data[INT]; void segtreebuild(ll p,ll l,ll r){ tr[p].l=l,tr[p].r=r; if(l==r){ tr[p].data=data[l]; } else{ ll mid=(l+r)/2; segtreebuild(2*p,l,mid); segtreebuild(2*p+1,mid+1,r); //在这里进行区间合并操作 tr[p].data=tr[2*p].data+tr[2*p+1].data; } } //懒标记传递 void pushdown(ll p) { if (tr[p].lztag != 0) { tr[p*2].lztag += tr[p].lztag; tr[p*2+1].lztag += tr[p].lztag; tr[p*2].data += tr[p].lztag * (tr[p*2].r - tr[p*2].l + 1); tr[p*2+1].data += tr[p].lztag * (tr[p*2+1].r - tr[p*2+1].l + 1); tr[p].lztag = 0; // 清除当前节点的懒标记 } } //点修改O(logn) void pset(ll now, ll pos, ll addnum) { if (tr[now].l == tr[now].r) { //点修改操作 tr[now].data += addnum; return; } pushdown(now); // 下传懒标记 ll mid = (tr[now].l + tr[now].r) / 2; if (pos <= mid) pset(now*2, pos, addnum); else pset(now*2+1, pos, addnum); //合并操作 tr[now].data = tr[now*2].data + tr[now*2+1].data; } //区间修改 void add(ll p, ll l, ll r, ll addnum) { if (tr[p].l >= l && tr[p].r <= r) { tr[p].lztag += addnum; // 累加懒标记 tr[p].data += addnum * (tr[p].r - tr[p].l + 1); // 更新当前节点数据 return; } pushdown(p); ll mid = (tr[p].l + tr[p].r) / 2; if (l <= mid) { add(2 * p, l, r, addnum); } if (r > mid) { add(2 * p + 1, l, r, addnum); } tr[p].data = tr[2 * p].data + tr[2 * p + 1].data; } //区间查询O(logn) ll query(ll p, ll l, ll r) { if (l <= tr[p].l && r >= tr[p].r) { return tr[p].data; } pushdown(p); // 处理懒标记 ll mid = (tr[p].l + tr[p].r) / 2, sum = 0; if (l <= mid) sum += query(p*2, l, r); if (r > mid) sum += query(p*2+1, l, r); return sum; } int main(){ ll n,m,temp,x,y,k; scanf("%lld%lld",&n,&m); for (ll i = 1; i <= n; ++i) { scanf("%lld",&data[i]); } segtreebuild(1,1,n); for (ll i = 0; i < m; ++i) { scanf("%lld",&temp); if(temp==1){ scanf("%lld%lld%lld",&x,&y,&k); add(1,x,y,k); }else{ scanf("%lld%lld",&x,&y); printf("%lld\n",query(1,x,y)); } } }