とりあえず欲しいのは出力クエリでの \((i,j)\) 成分の値. これは, \(i\) 行目に対する最後の代入クエリと,それ以降の \(i\) 行目に対する加算クエリの和が分かれば十分. これらは,クエリを先読みすることで得られる.
必要なデータ構造は,範囲加算と点取得. 点加算,点取得でもimos法の要領で代用可能.
使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"
int main() {
ll n, m, q;
cin >> n >> m >> q;
vll type(q), a(q), b(q), c(q);
vll ids(q, -1);
vvll subt(q);
vll ans;
rep(qi,q){
cin >> type[qi];
if(type[qi] == 1){
cin >> a[qi] >> b[qi] >> c[qi];
a[qi]--;
}else if(type[qi] == 2){
cin >> a[qi] >> b[qi];
a[qi]--;
lastest[a[qi]] = {qi, b[qi]};
}else{
cin >> a[qi] >> b[qi];
a[qi]--, b[qi]--;
const auto [j, x] = lastest[a[qi]];
const ll id = ans.size();
ans.emplace_back(x);
ids[qi] = id;
if(j >= 0){
subt[j].push_back(qi);
}
}
}
segtree<ll, op, e> st(m+1);
rep(qi,q){
if(type[qi] == 1){
st.set(a[qi], st.get(a[qi]) + c[qi]);
st.set(b[qi], st.get(b[qi]) - c[qi]);
}else if(type[qi] == 2){
for(const ll j: subt[qi]){ // j in q : time of output query
ans[ids[j]] -= st.prod(0, b[j]+1);
}
}else{
ans[ids[qi]] += st.prod(0, b[qi]+1);
}
}
for(ll x: ans){
cout << x << endl;
}
return 0;
}