競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 253F

ABC253F

とりあえず欲しいのは出力クエリでの \((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);
  vector<pll> lastest(n, {-1, 0});
  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;
}