Problem p03483 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
using vi = vector<i64>;
using vvi = vector<vi>;
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

class SqrtDecomp {
  int B;
  using ii = pair<int, int>;
  vi as;
  vector<deque<i64>> ds;
  vector<unordered_set<i64>> ss;
  inline i64 id(ii a) { return i64(2e9) * a.first + a.second; }
  i64 shift_begin(int k, int l, const i64 a) {
    i64 ret = ds[k].back();
    ds[k].pop_back();
    ss[k].erase(ret);
    ds[k].insert(ds[k].begin() + l, a);
    ss[k].insert(a);
    return ret;
  }
  i64 shift(int k, const i64 a) {
    ds[k].push_front(a);
    ss[k].insert(a);
    i64 ret = ds[k].back();
    ds[k].pop_back();
    ss[k].erase(ret);
    return ret;
  }
  void shift_end(int k, int r, const i64 a) {
    ss[k].erase(ds[k][r]);
    ds[k].erase(ds[k].begin() + r);
    ss[k].insert(a);
    ds[k].insert(ds[k].begin(), a);
  }
  void shift_begin_end(int k, int l, int r) {
    ds[k].insert(ds[k].begin() + l, ds[k][r]);
    ds[k].erase(ds[k].begin() + r + 1);
  }

public:
  SqrtDecomp(const vi &as) : as(as) {
    for (B = 1; B * B < as.size(); B++)
      ;
    ds = vector<deque<i64>>(B);
    ss = vector<unordered_set<i64>>(B);
    for (int i = 0; i < B * B; i++) {
      if (i < as.size()) {
        i64 k = id(ii(i, as[i]));
        ds[i / B].push_back(k);
        ss[i / B].insert(k);
      } else {
        i64 k = id(ii(i, -1));
        ds[i / B].push_back(k);
        ss[i / B].insert(k);
      }
    }
  }
  void rotate(int l, int r) {
    int li = l / B, ri = r / B;
    if (li != ri) {
      i64 s = ds[ri][r % B];
      s = shift_begin(li, l % B, s);
      for (int i = li + 1; i < ri; i++) {
        s = shift(i, s);
      }
      shift_end(ri, r % B, s);
    } else {
      shift_begin_end(li, l % B, r % B);
    }
  }
  int find(int k, int pre) {
    i64 t = id(ii(k, as[k]));
    int i;
    for (i = pre / B; i < B; i++) {
      if (ss[i].count(t))
        break;
    }
    if (i == B) {
      for (i = 0; i < pre / B; i++) {
        if (ss[i].count(t))
          break;
      }
    }

    for (int j = pre % B; j < B; j++) {
      if (ds[i][j] == t) {
        return i * B + j;
      }
    }
    for (int j = 0; j < pre % B; j++) {
      if (ds[i][j] == t) {
        return i * B + j;
      }
    }
    assert(0);
  }
};

int main() {
  assert(freopen("/Users/xuzijian/Downloads/in/35.txt", "r", stdin));
  // assert(freopen("/Users/xuzijian/atcoder/arc088/tmp", "w", stdout));
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  string s;
  cin >> s;
  queue<i64> que[26];
  int cnt[26] = {};
  vi as;
  for (int i = 0; i < s.size(); i++) {
    as.push_back(s[i]);
  }
  SqrtDecomp sq(as);
  for (int i = 0; i < s.size(); i++) {
    int c = s[i] - 'a';
    cnt[c]++;
  }
  int ok = 2;
  for (int i = 0; i < 26; i++) {
    if (cnt[i] % 2) {
      ok--;
    }
  }
  if (ok <= 0) {
    cout << -1 << endl;
    return 0;
  }
  int need[26] = {};
  for (int i = 0; i < 26; i++) {
    need[i] = cnt[i] / 2;
  }
  i64 ans = 0;
  int id = 0;
  vi pal(s.size());
  using ii = pair<int, int>;
  queue<ii> que2;
  for (int i = 0; i < s.size(); i++) {
    int c = s[i] - 'a';
    if (need[c]) {
      que2.push(ii(i, c));
      need[c]--;
    } else {
      que[c].push(i);
    }
  }

  int pre = 0;
  while (1) {
    if (id == s.size())
      break;
    if (id < s.size() / 2) {
      int k = que2.front().first;
      int ch = que2.front().second;
      pre = sq.find(k, pre);
      ans += pre - id;
      que2.pop();
      pal[id] = ch;
      if (id != pre) {
        sq.rotate(id, pre);
      }
      id++;
    } else if (s.size() % 2 && id == s.size() / 2) {
      for (int i = 0; i < 26; i++) {
        if (cnt[i] % 2) {
          int t = que[i].front();
          pre = sq.find(t, pre);
          ans += pre - id;
          que[i].pop();
          // pal += 'a' + i;
          if (pre - id != 0) {
            sq.rotate(id, pre);
          }
          id++;
          break;
        }
      }
    } else {
      int r = s.size() - 1 - id;
      int c = pal[r];
      // assert(que[c].size());
      int t = que[c].front();
      pre = sq.find(t, pre);
      ans += pre - id;
      que[c].pop();
      // pal += 'a' + c;
      if (pre - id != 0) {
        sq.rotate(id, pre);
      }
      id++;
    }
  }
  // cout << pal << endl;
  cout << ans << endl;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
using vi = vector<i64>;
using vvi = vector<vi>;
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

class SqrtDecomp {
  int B;
  using ii = pair<int, int>;
  vi as;
  vector<deque<i64>> ds;
  vector<unordered_set<i64>> ss;
  inline i64 id(ii a) { return i64(2e9) * a.first + a.second; }
  i64 shift_begin(int k, int l, const i64 a) {
    i64 ret = ds[k].back();
    ds[k].pop_back();
    ss[k].erase(ret);
    ds[k].insert(ds[k].begin() + l, a);
    ss[k].insert(a);
    return ret;
  }
  i64 shift(int k, const i64 a) {
    ds[k].push_front(a);
    ss[k].insert(a);
    i64 ret = ds[k].back();
    ds[k].pop_back();
    ss[k].erase(ret);
    return ret;
  }
  void shift_end(int k, int r, const i64 a) {
    ss[k].erase(ds[k][r]);
    ds[k].erase(ds[k].begin() + r);
    ss[k].insert(a);
    ds[k].insert(ds[k].begin(), a);
  }
  void shift_begin_end(int k, int l, int r) {
    ds[k].insert(ds[k].begin() + l, ds[k][r]);
    ds[k].erase(ds[k].begin() + r + 1);
  }

public:
  SqrtDecomp(const vi &as) : as(as) {
    for (B = 1; B * B < as.size(); B++)
      ;
    ds = vector<deque<i64>>(B);
    ss = vector<unordered_set<i64>>(B);
    for (int i = 0; i < B * B; i++) {
      if (i < as.size()) {
        i64 k = id(ii(i, as[i]));
        ds[i / B].push_back(k);
        ss[i / B].insert(k);
      } else {
        i64 k = id(ii(i, -1));
        ds[i / B].push_back(k);
        ss[i / B].insert(k);
      }
    }
  }
  void rotate(int l, int r) {
    int li = l / B, ri = r / B;
    if (li != ri) {
      i64 s = ds[ri][r % B];
      s = shift_begin(li, l % B, s);
      for (int i = li + 1; i < ri; i++) {
        s = shift(i, s);
      }
      shift_end(ri, r % B, s);
    } else {
      shift_begin_end(li, l % B, r % B);
    }
  }
  int find(int k, int pre) {
    i64 t = id(ii(k, as[k]));
    int i;
    for (i = pre / B; i < B; i++) {
      if (ss[i].count(t))
        break;
    }
    if (i == B) {
      for (i = 0; i < pre / B; i++) {
        if (ss[i].count(t))
          break;
      }
    }

    for (int j = pre % B; j < B; j++) {
      if (ds[i][j] == t) {
        return i * B + j;
      }
    }
    for (int j = 0; j < pre % B; j++) {
      if (ds[i][j] == t) {
        return i * B + j;
      }
    }
    assert(0);
  }
};

int main() {
  // assert(freopen("/Users/xuzijian/Downloads/in/35.txt", "r", stdin));
  // assert(freopen("/Users/xuzijian/atcoder/arc088/tmp", "w", stdout));
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  string s;
  cin >> s;
  queue<i64> que[26];
  int cnt[26] = {};
  vi as;
  for (int i = 0; i < s.size(); i++) {
    as.push_back(s[i]);
  }
  SqrtDecomp sq(as);
  for (int i = 0; i < s.size(); i++) {
    int c = s[i] - 'a';
    cnt[c]++;
  }
  int ok = 2;
  for (int i = 0; i < 26; i++) {
    if (cnt[i] % 2) {
      ok--;
    }
  }
  if (ok <= 0) {
    cout << -1 << endl;
    return 0;
  }
  int need[26] = {};
  for (int i = 0; i < 26; i++) {
    need[i] = cnt[i] / 2;
  }
  i64 ans = 0;
  int id = 0;
  vi pal(s.size());
  using ii = pair<int, int>;
  queue<ii> que2;
  for (int i = 0; i < s.size(); i++) {
    int c = s[i] - 'a';
    if (need[c]) {
      que2.push(ii(i, c));
      need[c]--;
    } else {
      que[c].push(i);
    }
  }

  int pre = 0;
  while (1) {
    if (id == s.size())
      break;
    if (id < s.size() / 2) {
      int k = que2.front().first;
      int ch = que2.front().second;
      pre = sq.find(k, pre);
      ans += pre - id;
      que2.pop();
      pal[id] = ch;
      if (id != pre) {
        sq.rotate(id, pre);
      }
      id++;
    } else if (s.size() % 2 && id == s.size() / 2) {
      for (int i = 0; i < 26; i++) {
        if (cnt[i] % 2) {
          int t = que[i].front();
          pre = sq.find(t, pre);
          ans += pre - id;
          que[i].pop();
          // pal += 'a' + i;
          if (pre - id != 0) {
            sq.rotate(id, pre);
          }
          id++;
          break;
        }
      }
    } else {
      int r = s.size() - 1 - id;
      int c = pal[r];
      // assert(que[c].size());
      int t = que[c].front();
      pre = sq.find(t, pre);
      ans += pre - id;
      que[c].pop();
      // pal += 'a' + c;
      if (pre - id != 0) {
        sq.rotate(id, pre);
      }
      id++;
    }
  }
  // cout << pal << endl;
  cout << ans << endl;
}