E - Sum of Subarrays 解説
by
physics0523
過剰な が付きますが、 segment tree で解くこともできます。
区間和 を累積和を使って という形に変形すると、 の連続する区間を segment tree に乗せやすくなります。
segtree のモノイドとして、以下のものを持っています。以下の情報があれば求解するのに十分です。
- 区間内の の総和
- 区間の長さ
- 区間内での答え
実装例 (C++):
Copy
#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;}
#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;
}
投稿日時:
最終更新: