Problem p01920 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAX_N = 1 << 17;

struct LazySegTree {
  int n;
  struct S {
    int flag;
    int sum;
    int l, r;
    S() : flag(0), sum(0), l(0), r(0) {}
  };
  S node[2 * MAX_N - 1];
  void init(int n_) {
    n = 1;
    while (n < n_)
      n *= 2;
  }

  void propagate(int k, int len) {
    S &t = node[k];
    if (!t.flag)
      return;
    if (2 * k + 1 < 2 * n - 1) {
      S &l = node[2 * k + 1];
      S &r = node[2 * k + 2];
      l.flag = r.flag = 1;
      int x = t.l;
      l.l = l.r = r.l = r.r = x;
      l.sum = r.sum = x;
    }
    t.flag = 0;
  }

  void merge(int k, int len) {
    S &t = node[k];
    S &l = node[2 * k + 1];
    S &r = node[2 * k + 2];
    t.sum = l.sum + r.sum;
    if (l.r && r.l)
      t.sum--;
    t.l = l.l;
    t.r = r.r;
  }

  void query(int a, int b, int x) { query(a, b, x, n, 0, 0, n); }

  void query(int a, int b, int x, int len, int k, int l, int r) {
    if (r <= a || b <= l)
      return;
    propagate(k, len);
    if (a <= l && r <= b) {
      node[k].flag = 1;
      node[k].l = node[k].r = x;
      node[k].sum = x;
      propagate(k, len);
      return;
    }
    query(a, b, x, len / 2, k * 2 + 1, l, (l + r) / 2);
    query(a, b, x, len / 2, k * 2 + 2, (l + r) / 2, r);
    merge(k, len);
  }
};

int n;
int b[100000];

LazySegTree st;

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin >> n;
  st.init(n);
  string s;
  cin >> s;
  for (int i = 0; i < n; i++) {
    b[i] = s[i] - '0';
  }

  for (int i = 0; i < n; i++) {
    int idx = i + st.n - 1;
    auto &node = st.node[idx];
    node.l = node.r = node.sum = b[i];
  }
  for (int i = st.n - 2; i >= 0; i--) {
    st.merge(i, -1);
  }

  int q;
  cin >> q;
  for (int t = 0; t < q; t++) {
    int l, r, x;
    cin >> l >> r >> x;
    l--;
    st.query(l, r, x);
    auto node = st.node[0];
    cout << node.sum << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int B = 320;
int n;
int b[100000];
int tb[100000];
int M[B];
int tM[B];
int fM[B];
int gM[B];

int rec(int i) {
  if (tb[i] > tM[i])
    return b[i];
  return M[i / B];
}

int f() {
  int ret = 0, i = 0;
  auto single = [&]() {
    ret += rec(i);
    i++;
  };
  auto multi = [&]() {
    ret += fM[i / B];
    i += B;
  };
  while (i < n && i + B < n)
    multi();
  while (i < n)
    single();
  return ret;
}

int g() {
  int ret = 0, i = 0;
  auto single = [&]() {
    if (i + 1 < n)
      ret += rec(i) * rec(i + 1);
    i++;
  };
  auto multi = [&]() {
    ret += gM[i / B];
    if (i + B < n)
      ret += rec(i + B - 1) * rec(i + B);
    i += B;
  };
  while (i < n && i + B < n)
    multi();
  while (i < n)
    single();
  return ret;
}

void query(int l, int r, int x, int t) {
  int i = l;
  auto single = [&]() {
    fM[i / B] -= rec(i);
    if (i % B != 0)
      gM[i / B] -= rec(i - 1) * rec(i);
    if ((i + 1) % B != 0)
      gM[i / B] -= rec(i) * rec(i + 1);
    b[i] = x;
    tb[i] = t;
    fM[i] += b[i];
    if (i % B != 0)
      gM[i / B] += rec(i - 1) * rec(i);
    if ((i + 1) % B != 0)
      gM[i / B] += rec(i) * rec(i + 1);
    i++;
  };
  auto multi = [&]() {
    fM[i / B] = 0;
    gM[i / B] = 0;
    M[i / B] = x;
    tM[i / B] = t;
    fM[i / B] = x * B;
    gM[i / B] = x * (B - 1);
    i += B;
  };
  while (i < r && i % B)
    single();
  while (i < r && i + B < r)
    multi();
  while (i < r)
    single();
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin >> n;
  string s;
  cin >> s;
  for (int i = 0; i < n; i++) {
    b[i] = s[i] - '0';
    fM[i / B] += b[i];
  }
  for (int i = 0; i < n; i++) {
    if ((i + 1) % B)
      gM[i / B] += b[i] * b[i + 1];
  }

  memset(tM, -1, sizeof tM);

  int q;
  cin >> q;
  for (int t = 0; t < q; t++) {
    int l, r, x;
    cin >> l >> r >> x;
    l--;
    query(l, r, x, t);
    cout << f() - g() << endl;
  }
}