思路
只要记录线段树所有区间的一个左端点的值这个题就可以做完..
我们可以假设这个左端点是,对于每次修改操作,我们只要知道左端点的值,我们这个区间修改的值就会变得已知,就可以更新,子区间的值也可以更新.
总之还是线段树不熟练~.
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+5; struct Tree{ ll l,r,sum,lazy; }tr[N<<2]; int a[N]; void pushup(int u) { tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum; } void pushdown(int u) { if(tr[u].lazy) { tr[u<<1].lazy=tr[u].lazy; tr[u<<1].sum=(2ll*tr[u<<1].lazy+tr[u<<1].r-tr[u<<1].l)*(tr[u<<1].r-tr[u<<1].l+1)/2ll; tr[u<<1|1].lazy=tr[u].lazy+tr[u<<1].r-tr[u<<1].l+1; tr[u<<1|1].sum=(2ll*tr[u<<1|1].lazy+tr[u<<1|1].r-tr[u<<1|1].l)*(tr[u<<1|1].r-tr[u<<1|1].l+1)/2ll; tr[u].lazy=0; } } void update(int u,int l,int r,int val) { if(l>tr[u].r||r<tr[u].l) return; if(l<=tr[u].l&&tr[u].r<=r) { tr[u].lazy=(tr[u].l-l+val); tr[u].sum=(2ll*tr[u].lazy+tr[u].r-tr[u].l)*(tr[u].r-tr[u].l+1)/2ll; return; } pushdown(u); update(u<<1,l,r,val); update(u<<1|1,l,r,val); pushup(u); } ll ask(int u,int l,int r) { if(l>tr[u].r||r<tr[u].l) return 0; if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum; pushdown(u); return ask(u<<1,l,r)+ask(u<<1|1,l,r); } void build(int u,int l,int r) { tr[u].l=l,tr[u].r=r; if(l==r) { tr[u].sum=a[l]; return; } int mid=(l+r)>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); pushup(u); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); while(m--) { int op; scanf("%d",&op); if(op==1) { int l,r,k; scanf("%d%d%d",&l,&r,&k); update(1,l,r,k); } else { int l,r; scanf("%d%d",&l,&r); printf("%lld\n",ask(1,l,r)); } } return 0; }