E - Sum of Subarrays Editorial by physics0523


過剰な \(\log\) が付きますが、 segment tree で解くこともできます。
区間和 \(\sum_{k=l}^{r} A_k\) を累積和を使って \(B_{r+1} - B_{l}\) という形に変形すると、 \(B\) の連続する区間を segment tree に乗せやすくなります。

segtree のモノイドとして、以下のものを持っています。以下の情報があれば求解するのに十分です。

  • 区間内の \(B_k\) の総和 \(val\)
  • 区間の長さ \(len\)
  • 区間内での答え \(res\)

実装例 (C++):

#include<bits/stdc++.h>
#include<atcoder/all>

using namespace std;
using namespace atcoder;
using ll=long long;

typedef struct{
  ll val;
  ll len;
  ll res;
}S;

S e(){ return {0,0,0}; }
S op(S l,S r){
  S res;
  res.val=l.val+r.val;
  res.len=l.len+r.len;
  res.res=l.res+r.res;
  res.res+=l.len*r.val;
  res.res-=l.val*r.len;
  return res;
}

int main(){
  ll n,q;
  cin >> n >> q;
  vector<ll> a(n);
  for(auto &nx : a){cin >> nx;}
  vector<S> ini(n+1);
  S cur={0,1,0};
  ini[0]=cur;
  for(ll i=1;i<=n;i++){
    cur.val+=a[i-1];
    ini[i]=cur;
  }
  segtree<S,op,e> seg(ini);
  vector<ll> res;
  while(q>0){
    q--;
    ll l,r;
    cin >> l >> r;
    l--;
    cout << seg.prod(l,r+1).res << "\n";
  }
  return 0;
}

posted:
last update: