Problem p03527 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;

using ui = uint32_t;

const int maxn = 50100;
ui _q[4000 * maxn];
ui *q[maxn];
int qmem[maxn];
int m;

void qset(int x, int y, bool val = true) {
  assert((m - y) / 32 < qmem[x]);
  q[x][(m - y) / 32] |= (ui(1) << ((m - y) % 32));
  if (!val) {
    q[x][(m - y) / 32] ^= (ui(1) << ((m - y) % 32));
  }
}

bool qget(int x, int y) {
  assert((m - y) / 32 < qmem[x]);
  return q[x][(m - y) / 32] & (ui(1) << ((m - y) % 32));
}

void qor(int x, int y) {
  assert(x > y);
  for (int i = 0; i < qmem[x]; ++i) {
    q[x][i] |= q[y][i];
  }
}

int qfind_first(int x) {
  for (int i = qmem[x] - 1; i >= 0; --i) {
    if (!q[i]) {
      continue;
    }
    for (int j = 31; j >= 0; --j) {
      int c = m - (i * 32 + j);
      if (c <= x) {
        continue;
      }
      if (qget(x, c)) {
        return c;
      }
    }
  }
  return maxn;
}

signed main() {
#ifdef LOCAL
  assert(freopen("e.in", "r", stdin));
#endif
  string s;
  int qs;
  cin >> s >> qs;
  int n = (int)s.size();
  m = n / 2;
  int OFF = 0;
  for (int i = m; i >= 0; --i) {
    int mem = (m - i + 1 + 31) / 32;
    q[i] = _q + OFF;
    qmem[i] = mem;
    OFF += mem;
  }

  for (int i = 0; i < qs; ++i) {
    int l, r;
    cin >> l >> r;
    --l;
    int nl, nr;
    if (r <= m) {
      nl = l;
      nr = r;
    } else if (l >= n - m) {
      nl = n - r;
      nr = n - l;
    } else {
      nl = l;
      nr = n - r;
      if (nl >= nr) {
        swap(nl, nr);
      }
    }
    if (nl != nr) {
      assert(nr > nl);
      qset(nl, nr);
      // cerr << nl << ' ' << nr << '\n';
    }
  }
  vector<int> val(m);
  for (int i = 0; i < m; ++i) {
    val[i] = (s[i] - s[n - 1 - i] + 26) % 26;
  }
  int add = 0;
  vector<int> delta(m + 1);
  // for (int i = 0; i < m; ++i) {
  // cerr << val[i] << '\n';
  //}
  for (int i = 0; i < m; ++i) {
    // cerr << i << ' ' << val[i] << '\n';
    add = (add - delta[i] + 26) % 26;
    val[i] = (val[i] - add + 26) % 26;
    int to = qfind_first(i);
    if (val[i] != 0 && to == maxn) {
      cout << "NO\n";
      return 0;
    }
    if (val[i] != 0) {
      // cerr << "add " << i << ' ' << to << ' ' << val[i] << '\n';
      delta[to] = (delta[to] + val[i]) % 26;
      add = (val[i] + add) % 26;
    }
    if (to != maxn) {
      qor(to, i);
      // q[to] |= q[i];
    }
  }
  cout << "YES\n";
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;

using ui = uint32_t;

const int maxn = 50100;
ui _q[4000 * maxn];
ui *q[maxn];
int qmem[maxn];
int m;

void qset(int x, int y, bool val = true) {
  assert((m - y) / 32 < qmem[x]);
  q[x][(m - y) / 32] |= (ui(1) << ((m - y) % 32));
  if (!val) {
    q[x][(m - y) / 32] ^= (ui(1) << ((m - y) % 32));
  }
}

bool qget(int x, int y) {
  assert((m - y) / 32 < qmem[x]);
  return q[x][(m - y) / 32] & (ui(1) << ((m - y) % 32));
}

void qor(int x, int y) {
  assert(x > y);
  for (int i = 0; i < qmem[x]; ++i) {
    q[x][i] |= q[y][i];
  }
}

int qfind_first(int x) {
  for (int i = qmem[x] - 1; i >= 0; --i) {
    if (!q[x][i]) {
      continue;
    }
    for (int j = 31; j >= 0; --j) {
      int c = m - (i * 32 + j);
      if (c <= x) {
        continue;
      }
      if (qget(x, c)) {
        return c;
      }
    }
  }
  return maxn;
}

signed main() {
#ifdef LOCAL
  assert(freopen("e.in", "r", stdin));
#endif
  string s;
  int qs;
  cin >> s >> qs;
  int n = (int)s.size();
  m = n / 2;
  int OFF = 0;
  for (int i = m; i >= 0; --i) {
    int mem = (m - i + 1 + 31) / 32;
    q[i] = _q + OFF;
    qmem[i] = mem;
    OFF += mem;
  }

  for (int i = 0; i < qs; ++i) {
    int l, r;
    cin >> l >> r;
    --l;
    int nl, nr;
    if (r <= m) {
      nl = l;
      nr = r;
    } else if (l >= n - m) {
      nl = n - r;
      nr = n - l;
    } else {
      nl = l;
      nr = n - r;
      if (nl >= nr) {
        swap(nl, nr);
      }
    }
    if (nl != nr) {
      assert(nr > nl);
      qset(nl, nr);
      // cerr << nl << ' ' << nr << '\n';
    }
  }
  vector<int> val(m);
  for (int i = 0; i < m; ++i) {
    val[i] = (s[i] - s[n - 1 - i] + 26) % 26;
  }
  int add = 0;
  vector<int> delta(m + 1);
  // for (int i = 0; i < m; ++i) {
  // cerr << val[i] << '\n';
  //}
  for (int i = 0; i < m; ++i) {
    // cerr << i << ' ' << val[i] << '\n';
    add = (add - delta[i] + 26) % 26;
    val[i] = (val[i] - add + 26) % 26;
    int to = qfind_first(i);
    if (val[i] != 0 && to == maxn) {
      cout << "NO\n";
      return 0;
    }
    if (val[i] != 0) {
      // cerr << "add " << i << ' ' << to << ' ' << val[i] << '\n';
      delta[to] = (delta[to] + val[i]) % 26;
      add = (val[i] + add) % 26;
    }
    if (to != maxn) {
      qor(to, i);
      // q[to] |= q[i];
    }
  }
  cout << "YES\n";
}