其实想了很久,我也不觉得是自己脑子反应慢,因为老会纠结一些奇怪的点..
也许,因此也对算法有了奇怪的理解吧。
#1,lazytag的作用是,在对同一区间进行多次操作再统一提问时,相当于先存操作数,提问时再一并处理。
lazytag下放的尽头是?放到树的某个节点管辖的区间可以被修改的区间完全包含时,就停止了。
所以最后lazytag的下放情况其实是:下放到最大的节点可以完全管到的区间,由多个这样的区间组成。
这个跟普通线段树的查询操作是一样的。
#2.为什么update的时候要pushdown,为什么还要tree[i].sum=tree[i*2].sum+tree....
待填坑。。困了
#include<bits/stdc++.h> using namespace std; typedef long long ll; struct node{ ll l,r,sum,lazy; }tree[1000000]; ll n,m,input[1000000]; void build(ll i,ll l,ll r) { if(l==r) { tree[i].l=l; tree[i].r=r; tree[i].sum=input[l]; return; } tree[i].lazy=0; tree[i].l=l; tree[i].r=r; ll mid=(l+r)>>1; build(i*2,l,mid); build(i*2+1,mid+1,r); tree[i].sum=tree[i*2].sum+tree[i*2+1].sum; } void pushdown(ll i) { if(tree[i].lazy!=0) { tree[i*2].lazy+=tree[i].lazy; tree[i*2+1].lazy+=tree[i].lazy; ll mid=(tree[i].l+tree[i].r)>>1; tree[i*2].sum+=tree[i].lazy*(mid-tree[i].l+1); tree[i*2+1].sum+=tree[i].lazy*(tree[i].r-mid); tree[i].lazy=0; } } void update(ll i,ll l,ll r,ll k) { if(tree[i].l>=l&&tree[i].r<=r) { tree[i].lazy+=k; tree[i].sum+=k*(tree[i].r-tree[i].l+1); return; } pushdown(i); ll mid=(tree[i].l+tree[i].r)>>1; if(tree[i*2].r>=l) { update(i*2,l,r,k); } if(tree[i*2+1].l<=r) { update(i*2+1,l,r,k); } tree[i].sum=tree[i*2].sum+tree[i*2+1].sum; return; } ll query(ll i,ll l,int r) { if(tree[i].l>=l&&tree[i].r<=r) { return tree[i].sum; } pushdown(i); ll ans=0; if(tree[i*2].r>=l) { ans+=query(i*2,l,r); } if(tree[i*2+1].l<=r) { ans+=query(i*2+1,l,r); } return ans; } int main() { /* 5 5 1 5 4 2 3 2 2 4 1 2 3 2 2 3 4 1 1 5 1 2 1 4 */ //freopen("9231.in","r",stdin); cin>>n>>m; for(ll i=1;i<=n;i++) { scanf("%lld",&input[i]); } build(1,1,n); for(ll i=1;i<=m;i++) { int a; cin>>a; if(a==2) { ll f,t; scanf("%lld%lld",&f,&t); cout<<query(1,f,t)<<endl; } else { ll from,to,k; scanf("%lld%lld%lld",&from,&to,&k); update(1,from,to,k); } } }