CODEVS 1082 (区间查询+区间求和)
题目链接:http://codevs.cn/problem/1082/
注意更新区间求和时,应该加上的是这一段区间包含的元素的个数乘以更新的值
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <vector> #include <cstring> #include <map> #define mem(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn = 4000005; const ll INF = 0x3f3f3f3f3f; int dir[8][2]= {0,1,1,0,0,-1,-1,0,1,-1,-1,-1,1,1,-1,1}; int dir2[4][2]= {0,1,0,-1,1,0,-1,0}; bool flag; ll a[maxn],sum[maxn],n,ans,num[maxn]; struct node{ ll l; ll r; }b[maxn]; void pushup(ll k) { sum[k] = sum[k*2] + sum[k*2+1]; } void build(ll k,ll l,ll r)//递归建树 { if(l == r) { b[k].l = l,b[k].r = r; sum[k] = a[l]; return ; } else { ll mid = (l+r) / 2; b[k].l = l,b[k].r=r; build(k<<1,l,mid); build(k*2+1,mid+1,r); pushup(k); } } void pushdown(ll k) { if(num[k]){ num[k<<1] += num[k]; num[k*2+1] += num[k]; sum[k<<1] += (b[k*2].r-b[k*2].l+1)*num[k]; sum[k*2+1] += (b[k*2+1].r-b[k*2+1].l+1)*num[k]; num[k] = 0; } } void update(ll l,ll r,ll L,ll R,ll k,ll v)//单点更新 { if(L >= l && R <= r) { sum[k] += (b[k].r-b[k].l+1)*v; num[k] += v; return ; } else { pushdown(k); ll mid = (L + R) / 2; if(l <= mid) update(l,r,L,mid,k*2,v); if(mid < r) update(l,r,mid+1,R,k*2+1,v); pushup(k); } } void Search(ll l,ll r,ll L,ll R,ll k)//区间查询 { if(L >= l&& R <= r) { ans += sum[k]; return; } pushdown(k); ll mid = (L + R) / 2; if(mid >= l) Search(l,r,L,mid,k*2); if(mid < r) Search(l,r,mid+1,R,k*2+1); } int main() { ll m; cin >> n; for(ll i = 1; i <= n; i++) { cin >> a[i]; } mem(sum); build(1,1,n);//建树 ll z,x,c,s; cin >> m; for(ll i = 1; i <= m; i++) { cin >> z; if(z == 1) { cin >> x >> c >> s; update(x,c,1,n,1,s); } else { cin >> x >> c; ans = 0; Search(x,c,1,n,1); cout << ans << endl; } } return 0; }