单一标记线段树。
在给定数列上建树:build时读入即可。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=100010; 5 long long tag[N<<2],sum[N<<2],c; 6 void build(int,int,int),release(int,int,int),update(int), 7 add(int,int,int,long long),modify(int,int,int,int,int,long long); 8 long long query(int,int,int,int,int); 9 int main(){ 10 int x,y,n,q; 11 scanf("%d %d",&n,&q); 12 build(1,1,n); 13 for (int i=1;i<=q;i++){ 14 getchar(); 15 char ch=getchar(); 16 scanf("%d %d",&x,&y); 17 if (ch==‘C‘){ 18 scanf("%lld",&c); 19 modify(1,1,n,x,y,c); 20 } 21 else printf("%lld\n",query(1,1,n,x,y)); 22 } 23 } 24 void build(int i,int l,int r){ 25 tag[i]=0; 26 if (l==r){ 27 scanf("%lld",&sum[i]); 28 return; 29 } 30 int mid=(l+r)>>1; 31 build(i<<1,l,mid); 32 build(i<<1|1,mid+1,r); 33 update(i); 34 } 35 void update(int i){ 36 sum[i]=sum[i<<1]+sum[i<<1|1]; 37 } 38 void modify(int i,int l,int r,int L,int R,long long d){ 39 if (L<=l&&r<=R){ 40 add(i,l,r,d);return; 41 } 42 release(i,l,r); 43 int mid=(l+r)>>1; 44 if (L<=mid) modify(i<<1,l,mid,L,R,d); 45 if (R>mid) modify(i<<1|1,mid+1,r,L,R,d); 46 update(i); 47 } 48 void add(int i,int l,int r,long long d){ 49 tag[i]+=d; 50 sum[i]+=(r-l+1)*d; 51 } 52 void release(int i,int l,int r){ 53 if (tag[i]){ 54 int mid=(l+r)>>1; 55 add(i<<1,l,mid,tag[i]); 56 add(i<<1|1,mid+1,r,tag[i]); 57 tag[i]=0; 58 } 59 } 60 long long query(int i,int l,int r,int L,int R){ 61 if (L<=l&&r<=R) return sum[i]; 62 release(i,l,r); 63 int mid=(l+r)>>1; 64 long long ans=0; 65 if (L<=mid) ans+=query(i<<1,l,mid,L,R); 66 if (R>mid) ans+=query(i<<1|1,mid+1,r,L,R); 67 return ans; 68 }
STD
时间: 2024-11-03 21:37:51