POJ 3468 (线段树
线段树如果只进行自上而下的更新的话,并不必要把n扩大到2的幂,如果把自下而上的更新写成递归形式的话也不需要。
这题是经典的线段树应用,注意线段树的区间统一为左开右闭区间,没注意这个WA了几次
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<utility> #include<vector> #include<cstring> #include<cmath> #define INF 0x3fffffff #define pb push_back #define pn(x) cerr<<x<<endl using namespace std; typedef long long ll; typedef pair<int,int> P;///num,pos const int maxv=100005; typedef pair<int,ll> node; int N,Q; int a[maxv]; ll data[maxv*4];////除了b以外其它的和,区间内 ll datb[maxv*4];/////区间内对每个数字加上的和 void init(int k,int l,int r){ if(r-l==1){ data[k]=a[l]; return; } int chl=k*2+1,chr=k*2+2,m=(r+l)/2; init(chl,l,m); init(chr,m,r); data[k]=data[chl]+data[chr]; return; } void update(int k,int c,int a,int b,int l,int r){ if(a>=r||b<l) return; if(a<=l&&b>=r-1){ datb[k]+=c; return; } data[k]+=c*(min(r,b+1)-max(a,l)); int chl=k*2+1,chr=k*2+2,m=(r+l)/2; if(r-l>1){ update(chl,c,a,b,l,m); update(chr,c,a,b,m,r); } return; } ll quary(int k,int a,int b,int l,int r){ if(a>=r||b<l) return 0; if(a<=l&&b>=r-1) return data[k]+datb[k]*(min(r,b+1)-max(a,l)); int chl=k*2+1,chr=k*2+2,m=(r+l)/2; ll ans=0; ans+=datb[k]*(min(r,b+1)-max(a,l)); if(r-l>1){ ans+=quary(chl,a,b,l,m); ans+=quary(chr,a,b,m,r); } return ans; } int main(){ freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); cin>>N>>Q; for(int i=0;i<N;i++) scanf("%d",&a[i]); init(0,0,N); while(Q--){ char q; cin>>q; if(q=='Q'){ int a,b; scanf("%d%d",&a,&b); printf("%I64d\n",quary(0,a-1,b-1,0,N)); } else{ int a,b,c; scanf("%d%d%d",&a,&b,&c); update(0,c,a-1,b-1,0,N); } } return 0; }

浙公网安备 33010602011771号