luogu P3372 【模板】线段树 1
线段树专门用来处理区间问题的,包括最大值,最小值,和
#include<cstdio> #include<iostream> using namespace std; long long n,m; long long s[1000010],tre[1000010],lan[1000010]; void build(long long i,long long l,long long r) { if(l==r) { tre[i]=s[l]; return; } long long mid=l+r>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); tre[i]=tre[i<<1]+tre[i<<1|1]; } void jia(long long i,long long l,long long r,long long x,long long y,int k) {//printf("*******l=%lld,r=%lld ",l,r); if(x<=l&&r<=y) { lan[i]+=k; //for(long long o=1;o<=9;o++) printf("tre[%lld]=%lld,lan[%lld]=%lld ",o,tre[o],o,lan[o]); return; } long long mid=(l+r)>>1; if(mid>=x) jia(i<<1,l,mid,x,y,k); if(mid+1<=y) jia(i<<1|1,mid+1,r,x,y,k); int a=max(l,x),b=min(r,y); tre[i]+=k*(b-a+1); //for(long long o=1;o<=9;o++) printf("tre[%lld]=%lld,lan[%lld]=%lld ",o,tre[o],o,lan[o]); } long long he(long long i,long long l,long long r,long long x,long long y) { //printf("*******l=%lld,r=%lld ",l,r); if(l>=x&&r<=y) { //for(long long o=1;o<=9;o++) printf("tre[%lld]=%lld,lan[%lld]=%lld ",o,tre[o],o,lan[o]); //printf("-------%lld ",tre[i]+lan[i]*(l-r+1)); return tre[i]+lan[i]*(r-l+1); } long long mid=l+r>>1,ans=0; tre[i]+=lan[i]*(r-l+1); lan[i<<1]+=lan[i]; lan[i<<1|1]+=lan[i]; lan[i]=0; //for(long long o=1;o<=9;o++) printf("tre[%lld]=%lld,lan[%lld]=%lld ",o,tre[o],o,lan[o]); if(mid>=x) ans+=he(i<<1,l,mid,x,y); if(mid+1<=y) ans+=he(i<<1|1,mid+1,r,x,y); return ans; } int main() { long long k,x,y; scanf("%lld%lld",&n,&m); for(int j=1;j<=n;j++) scanf("%lld",&s[j]); build(1,1,n); for(int j=0;j<m;j++) { scanf("%lld",&k); if(k==1) { scanf("%lld%lld%lld",&x,&y,&k); jia(1,1,n,x,y,k); } else if(k==2) { scanf("%lld%lld",&x,&y); printf("%lld ",he(1,1,n,x,y)); //for(long long o=1;o<=9;o++) printf("tre[%lld]=%lld,lan[%lld]=%lld ",o,tre[o],o,lan[o]); } } return 0; }