洛谷 2846 (线段树)
/* 如果是查询[2,4] 就是a2+a3+a4 a2+a3 a2 显然裸地线段树算不出来 我们维护前缀和 那查询的时候还要减去前多计算的 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 100010 #define ll long long using namespace std; ll n,m,tot,a[maxn],s[maxn],x,y,z; struct node { ll l,r,lc,rc,lazy,sum; }t[maxn*4]; ll init() { ll x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } void Build(ll li,ll ri) { ll k=++tot; t[k].l=li;t[k].r=ri; if(li==ri-1) { t[k].sum=s[li];return; } ll mid=(li+ri)/2; t[k].lc=tot+1;Build(li,mid); t[k].rc=tot+1;Build(mid,ri); t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum; } void Updata(int k) { t[t[k].lc].lazy+=t[k].lazy; t[t[k].rc].lazy+=t[k].lazy; t[t[k].lc].sum+=(t[t[k].lc].r-t[t[k].lc].l)*t[k].lazy; t[t[k].rc].sum+=(t[t[k].rc].r-t[t[k].rc].l)*t[k].lazy; t[k].lazy=0; } void Change(ll k,ll li,ll ri,ll data) { if(li<=t[k].l&&ri>=t[k].r) { t[k].sum+=(t[k].r-t[k].l)*data; t[k].lazy+=data; return; } if(t[k].lazy)Updata(k); ll mid=(t[k].l+t[k].r)/2; if(li<mid)Change(t[k].lc,li,ri,data); if(ri>mid)Change(t[k].rc,li,ri,data); t[k].sum=t[t[k].lc].sum+t[t[k].rc].sum; } ll Query(int k,int li,int ri) { if(li<=t[k].l&&ri>=t[k].r)return t[k].sum; ll r=0; if(t[k].lazy)Updata(k); ll mid=(t[k].l+t[k].r)/2; if(li<mid)r+=Query(t[k].lc,li,ri); if(ri>mid)r+=Query(t[k].rc,li,ri); return r; } int main() { n=init();m=init(); for(int i=1;i<=n;i++) a[i]=init(); for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]; Build(1,n+1); for(int i=1;i<=m;i++) { x=init();y=init();z=init(); if(x==1)Change(1,y,n+1,z); if(x==2)printf("%lld\n",Query(1,y,z+1)-(z-y+1)*Query(1,y-1,y)); } return 0; }