競技プログラミング日記

主に AtCoder の記事です

ACL Beginner Contest E問題

\(\def \set #1#2{\{ #1 \ \vert \ #2 \}}\)

 

解法

Lazy segtree. 文字列を 10進数とみなすので,segtree に乗せる. 区間の書き換えを保留しておくのがポイント.
Segtree の積が,文字列の結合に対応する. 10進数で考えるので,結合する前の桁数を持っておく必要がある. よって,segtree に乗せるデータは (10進数とみなしたときの値 \(x\) , 桁数 \(w\) ) で良い.
書きかえクエリのため,\(w\) 桁を \(d\) に変える処理が必要. つまり,\(d\cdots d\) が欲しい. これは \(d \cdot 1 \cdots 1 = d \cdot (10^{w}-1)/9\) と書ける.

実装

計算するときには \(w\) のまま使うことはなく, \(10^{w}\) だけあれば十分なので,この形で保持する.

使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"

struct S{
  // x : k 桁
  // p = 10^k
  mint x, p;
  S(){
    x = 0;
    p = 1;
  }

  S(mint x, mint p): x(x), p(p){}
};

S op (S a, S b){
  return S( a.x * b.p + b.x, a.p * b.p);
}

S e(){ return S(); }

S mapping(mint f, S x){
  if(f == 0) return x;
  else return S(f * (x.p - 1)/9, x.p);
}

mint composition (mint f, mint g){
  if(f == 0) return g;
  else return f;
}

mint id(){ return 0; }

int main() {
  ll n, q;
  cin >> n >> q;

  lazy_segtree<S, op,e, mint, mapping, composition, id> t(n);
  rep(i,n){
    t.set(i, S(1,10));
  }

  rep(i,q){
    ll l,r,d; cin >> l >> r >> d;
    --l;
    t.apply(l,r,d);
    cout << t.all_prod().x.val() << endl;
  }


  return 0;
}