【题目描述】
给定一个区间及区间上的数,每次有一个操作,在某段区间上加某个数后者询问某段区间的和。
【思路】
线段树的成段更新,要用到lazy_tag,要注意int会超范围,别的没什么了,最近学习了下hh大牛的线段树风格,学习下。
#include<cstdio> #define N 100010 #define lson l,mid,n<<1 #define rson mid+1,r,n<<1|1 typedef long long LL; using namespace std; LL sum[N<<2],add[N<<2]; void build(int l,int r,int n){ add[n]=0; if(l==r){ scanf("%lld",&sum[n]); return ; } int mid=(l+r)>>1; build(lson); build(rson); sum[n]=sum[n<<1]+sum[n<<1|1]; } void update(int ll,int rr,int aa,int l,int r,int n){ if(ll==l&&rr==r){ add[n]+=(LL)aa; sum[n]+=(LL)aa*(r-l+1); return; } int m=r-l+1; if(add[n]!=0){ add[n<<1]+=add[n]; add[n<<1|1]+=add[n]; sum[n<<1]+=add[n]*(m-(m>>1)); sum[n<<1|1]+=add[n]*(m>>1); add[n]=0; } int mid=(l+r)>>1; if(rr<=mid) update(ll,rr,aa,lson); else if(ll>mid) update(ll,rr,aa,rson); else update(ll,mid,aa,lson),update(mid+1,rr,aa,rson); sum[n]=sum[n<<1]+sum[n<<1|1]; } LL query(int ll,int rr,int l,int r,int n){ if(ll==l&&rr==r) return sum[n]; int m=r-l+1; if(add[n]!=0){ add[n<<1]+=add[n]; add[n<<1|1]+=add[n]; sum[n<<1]+=add[n]*(m-(m>>1)); sum[n<<1|1]+=add[n]*(m>>1); add[n]=0; } int mid=(l+r)>>1; if(rr<=mid) return query(ll,rr,lson); else if(ll>mid) return query(ll,rr,rson); else return query(ll,mid,lson)+query(mid+1,rr,rson); } int main(){ int n,q; while(~scanf("%d%d",&n,&q)){ build(1,n,1); while(q--){ char s; int a,b,c; getchar(); scanf("%c",&s); if(s=='Q'){ scanf("%d%d",&a,&b); printf("%lld\n",query(a,b,1,n,1)); } else if(s=='C'){ scanf("%d%d%d",&a,&b,&c); update(a,b,c,1,n,1); } } } return 0; }
浙公网安备 33010602011771号