uva 12501 - Bulky process of bulk reduction
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3945
题意:给一个序列,有两种操作:
1、query i j : a[i]*1+a[i+1]*2+a[i+2]*3+....+a[j]*(j+1)的值。
2、change i j u:把区间[i,j]的值都加上u。
思路:用线段树维护两个值s1,s2:
s1为当前区间[l,r]的a[l]*1+a[l+1]*2+a[l+2]*3+....+a[r]*(r+1)的值。
s2为当前区间[l,r]的a[l]+a[l+1]+a[l+2]+....a[r]的和。
这样如果包含有某个区间。那就这样区间的值就是s1+s2*c,c为这个区间前有多少个数。

#include<stdio.h> #include<string.h> #include<iostream> #define MD long long md = (l + r) >> 1 using namespace std; const long long maxn = 100005; struct nd{ long long tp,sum,s; }as[maxn*4]; long long n,m; inline void pushUp(long long rt,long long c) { as[rt].s = as[rt<<1].s + as[rt<<1|1].s; as[rt].sum = as[rt<<1].sum + as[rt<<1|1].s * c + as[rt<<1|1].sum; } inline void pushDown(long long rt,long long l,long long m,long long r){ as[rt<<1].tp += as[rt].tp; as[rt<<1|1].tp += as[rt].tp; as[rt<<1].s += (m - l + 1) * as[rt].tp; as[rt<<1|1].s += (r - m) * as[rt].tp; as[rt<<1].sum += (m - l + 2) * (m - l + 1) / 2 * as[rt].tp; as[rt<<1|1].sum += (r - m + 1) * (r - m) / 2 * as[rt].tp; as[rt].tp = 0; } void build(long long rt,long long l,long long r){ MD; as[rt].tp = 0; if(l==r){ as[rt].sum = 100; as[rt].s = 100; return ; } build(rt<<1,l,md); build(rt<<1|1,md+1,r); pushUp(rt,md-l+1); } void update(long long rt,long long l,long long r,long long L,long long R,long long v) { MD; if(L<=l && r<=R){ as[rt].tp += v; as[rt].sum += (r - l + 2) * (r - l + 1) / 2 * v; as[rt].s += (r - l + 1) * v; return ; } if(as[rt].tp)pushDown(rt,l,md,r); if(L<=md)update(rt<<1,l,md,L,R,v); if(R>md)update(rt<<1|1,md+1,r,L,R,v); pushUp(rt,md-l+1); } long long ans; void query(long long rt,long long l,long long r,long long L,long long R) { MD; if(L<=l && r<=R){ ans += as[rt].s * (l - L) + as[rt].sum; return ; } if(as[rt].tp)pushDown(rt,l,md,r); if(L<=md)query(rt<<1,l,md,L,R); if(R>md)query(rt<<1|1,md+1,r,L,R); pushUp(rt,md-l+1); } int main() { long long t,cas=0; scanf("%lld",&t); while(t--){ scanf("%lld %lld",&n,&m); build(1,1,n); char s[10]; long long l,r,v; printf("Case %lld:\n",++cas); while(m--){ scanf("%s",s); if(s[0]=='q'){ ans=0; scanf("%lld %lld",&l,&r); query(1,1,n,l,r); printf("%lld\n",ans); }else{ scanf("%lld %lld %lld",&l,&r,&v); update(1,1,n,l,r,v); } } } return 0; }