QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#368545#4631. Interesting String Problemhos_lyricRE 130ms11668kbC++1412.7kb2024-03-27 12:03:522024-03-27 12:03:53

Judging History

你现在查看的是最新测评结果

  • [2024-03-27 12:03:53]
  • 评测
  • 测评结果:RE
  • 用时:130ms
  • 内存:11668kb
  • [2024-03-27 12:03:52]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")

////////////////////////////////////////////////////////////////////////////////
// SA-IS
//   String: string, vector<int>, vector<long long>
//   if sigma <= n,  O(n) time, O(n) space
//   if sigma >  n,  O(n log n) time, O(n) space
template <class String> vector<int> suffixArrayRec(const String &as) {
  const int n = as.size();
  if (n == 0) return {};
  const auto minmaxA = minmax_element(as.begin(), as.end());
  const auto minA = *minmaxA.first, maxA = *minmaxA.second;
  if (static_cast<unsigned long long>(maxA) - minA >=
      static_cast<unsigned long long>(n)) {
    vector<int> us(n);
    for (int u = 0; u < n; ++u) us[u] = u;
    std::sort(us.begin(), us.end(), [&](int u, int v) -> bool {
      return (as[u] < as[v]);
    });
    int b = 0;
    vector<int> bs(n, 0);
    for (int i = 1; i < n; ++i) {
      if (as[us[i - 1]] != as[us[i]]) ++b;
      bs[us[i]] = b;
    }
    return suffixArrayRec(bs);
  }
  const int sigma = maxA - minA + 1;
  vector<int> pt(sigma + 1, 0), poss(sigma);
  for (int u = 0; u < n; ++u) ++pt[as[u] - minA + 1];
  for (int a = 0; a < sigma; ++a) pt[a + 1] += pt[a];
  // cmp[u] := (as[u, n) < as[u + 1, n))
  vector<bool> cmp(n);
  cmp[n - 1] = false;
  for (int u = n - 1; --u >= 0; ) {
    cmp[u] = (as[u] != as[u + 1]) ? (as[u] < as[u + 1]) : cmp[u + 1];
  }
  // ><,  nn - id (0 <= id < n)
  int nn = 0;
  vector<int> ids(n, 0);
  int last = n;
  vector<int> nxt(n, 0);
  // put ><, from the tail of each bucket
  vector<int> us(n, 0);
  memcpy(poss.data(), pt.data() + 1, sigma * sizeof(int));
  for (int u = n - 1; --u >= 1; ) if (!cmp[u - 1] && cmp[u]) {
    ids[u] = ++nn;
    nxt[u] = last;
    last = u;
    us[--poss[as[u] - minA]] = u;
  }
  // follow > backwards, from the head of each bucket
  memcpy(poss.data(), pt.data(), sigma * sizeof(int));
  us[poss[as[n - 1] - minA]++] = n - 1;
  for (int i = 0; i < n; ++i) {
    const int u = us[i];
    if (u && !cmp[u - 1]) us[poss[as[u - 1] - minA]++] = u - 1;
  }
  // follow < backwards, from the tail of each bucket
  memcpy(poss.data(), pt.data() + 1, sigma * sizeof(int));
  for (int i = n; --i >= 0; ) {
    const int u = us[i];
    if (u && cmp[u - 1]) us[--poss[as[u - 1] - minA]] = u - 1;
  }
  if (nn) {
    int vsLen = 0;
    vector<int> vs(nn);
    for (const int u : us) if (ids[u]) vs[vsLen++] = u;
    int b = 0;
    vector<int> bs(nn, 0);
    for (int j = 1; j < nn; ++j) {
      // as[v1, w1] (< or =) as[v0, w0]
      int v1 = vs[j - 1], v0 = vs[j];
      const int w1 = nxt[v1], w0 = nxt[v0];
      if (w1 - v1 != w0 - v0) {
        ++b;
      } else {
        for (; ; ++v1, ++v0) {
          if (v1 == n) { ++b; break; }
          if (as[v1] != as[v0]) { ++b; break; }
          if (v1 == w1) break;
        }
      }
      bs[nn - ids[vs[j]]] = b;
    }
    for (int u = 0; u < n; ++u) if (ids[u]) vs[nn - ids[u]] = u;
    const auto sub = suffixArrayRec(bs);
    // put ><, from the tail of each bucket
    memset(us.data(), 0, n * sizeof(int));
    memcpy(poss.data(), pt.data() + 1, sigma * sizeof(int));
    for (int j = nn; --j >= 0; ) {
      const int u = vs[sub[j]];
      us[--poss[as[u] - minA]] = u;
    }
    // follow > backwards, from the head of each bucket
    memcpy(poss.data(), pt.data(), sigma * sizeof(int));
    us[poss[as[n - 1] - minA]++] = n - 1;
    for (int i = 0; i < n; ++i) {
      const int u = us[i];
      if (u && !cmp[u - 1]) us[poss[as[u - 1] - minA]++] = u - 1;
    }
    // follow < backwards, from the tail of each bucket
    memcpy(poss.data(), pt.data() + 1, sigma * sizeof(int));
    for (int i = n; --i >= 0; ) {
      const int u = us[i];
      if (u && cmp[u - 1]) us[--poss[as[u - 1] - minA]] = u - 1;
    }
  }
  return us;
}

// us[i]: i-th suffix
// su[u]: index of as[u, n)
// hs[i]: longest common prefix of as[us[i - 1], n) and as[us[i], n)
struct SuffixArray {
  int n;
  bool rmq;
  vector<int> us, su, hs;
  SuffixArray() : n(0), rmq(false) {}
  SuffixArray(const string &as, bool rmq_) : rmq(rmq_) { build(as); }
  SuffixArray(const vector<int> &as, bool rmq_) : rmq(rmq_) { build(as); }
  SuffixArray(const vector<long long> &as, bool rmq_) : rmq(rmq_) { build(as); }
  template <class String> void build(const String &as) {
    n = as.size();
    us = suffixArrayRec(as);
    su.resize(n + 1);
    for (int i = 0; i < n; ++i) su[us[i]] = i;
    su[n] = -1;
    hs.assign(n, 0);
    for (int h = 0, u = 0; u < n; ++u) if (su[u]) {
      for (int v = us[su[u] - 1]; v + h < n && as[v + h] == as[u + h]; ++h) {}
      hs[su[u]] = h;
      if (h) --h;
    }
    if (rmq) {
      const int logN = n ? (31 - __builtin_clz(n)) : 0;
      hs.resize((logN + 1) * n - (1 << logN) + 1);
      for (int e = 0; e < logN; ++e) {
        int *hes = hs.data() + e * n;
        for (int i = 0; i <= n - (1 << (e + 1)); ++i) {
          hes[n + i] = min(hes[i], hes[i + (1 << e)]);
        }
      }
    }
  }
  // Returns longest common prefix of as[u, n) and as[v, n).
  //   0 <= u, v <= n
  //   Assumes rmq.
  inline int lcp(int u, int v) const {
    if (u == v) return n - u;
    int i = su[u], j = su[v];
    if (i > j) swap(i, j);
    const int e = 31 - __builtin_clz(j - i);
    return min(hs[e * n + i + 1], hs[e * n + j + 1 - (1 << e)]);
  }
};
////////////////////////////////////////////////////////////////////////////////

// 0 <= u <= n: suffix [u, n)  (n: root, empty string)
// n <  u <  m: LCA needed
struct SuffixTree {
  int n, m;
  SuffixArray sa;
  struct Node {
    int par, len, occ;
    inline int l() const { return occ; }
    inline int r() const { return occ + len; }
  };
  vector<Node> nodes;
  // considering character order
  vector<vector<int>> graph;
  int zeit = 0;
  vector<int> dis, fin, sid;

  SuffixTree() {}
  SuffixTree(const string &str, bool lastOcc) { build(str, lastOcc); }
  SuffixTree(const vector<int> &str, bool lastOcc) { build(str, lastOcc); }
  SuffixTree(const vector<long long> &str, bool lastOcc) { build(str, lastOcc); }
  template <class String> void build(const String &str, bool lastOcc) {
    n = str.size();
    m = n + 1;
    sa = SuffixArray(str, /*rmq=*/false);
    nodes.resize(2 * n + 1);
    graph.resize(2 * n + 1);
    nodes[n] = Node{/*par=*/-1, /*len=*/0, /*occ=*/lastOcc ? n : 0};
    int top = 0;
    vector<int> stack(n + 1);
    stack[0] = n;
    for (int i = 0; i < n; ++i) {
      const int u = sa.us[i];
      int v = -1;
      for (; nodes[stack[top]].len > sa.hs[i]; --top) {
        v = stack[top];
        nodes[nodes[v].par].occ = lastOcc ? max(nodes[nodes[v].par].occ, nodes[v].occ) : min(nodes[nodes[v].par].occ, nodes[v].occ);
      }
      if (nodes[stack[top]].len < sa.hs[i]) {
        const int w = m++;
        nodes[w] = Node{/*par=*/nodes[v].par, /*len=*/sa.hs[i], /*occ=*/nodes[v].occ};
        graph[nodes[v].par].back() = w;
        graph[w].push_back(v);
        stack[++top] = nodes[v].par = w;
      }
      nodes[u] = Node{/*par=*/stack[top], /*len=*/n - u, /*occ=*/u};
      graph[nodes[u].par].push_back(u);
      stack[++top] = u;
    }
    for (; top; --top) {
      const int v = stack[top];
      nodes[nodes[v].par].occ = lastOcc ? max(nodes[nodes[v].par].occ, nodes[v].occ) : min(nodes[nodes[v].par].occ, nodes[v].occ);
    }
    nodes.resize(m);
    graph.resize(m);
    dis.assign(m, -1);
    fin.assign(m, -1);
    dfs(n);
    assert(zeit == m);
    sid.assign(m, -1);
    for (int u = 0; u < m; ++u) sid[dis[u]] = u;
  }
  inline const Node &operator[](int u) const {
    return nodes[u];
  }
  inline int size(int u) const {
    return (~nodes[u].par) ? (nodes[u].len - nodes[nodes[u].par].len) : 1;
  }
  inline int parJ(int j) const {
    return dis[nodes[sid[j]].par];
  }

  void dfs(int u) {
    dis[u] = zeit++;
    for (const int v : graph[u]) dfs(v);
    fin[u] = zeit;
  }
};


// 0 for null
namespace seg {
using Value = int;
constexpr int MAX_NUM_NODES = 50'000'010;
int n, id, ls[MAX_NUM_NODES], rs[MAX_NUM_NODES];
Value vals[MAX_NUM_NODES];
void init(int n_) {
  n = n_;
  id = 1;
}
int newNode() {
  assert(id < MAX_NUM_NODES);
  const int u = id++;
  ls[u] = rs[u] = 0;
  vals[u] = Value();
  return u;
}
int build(int l, int r) {
  const int u = newNode();
  if (l + 1 == r) return u;
  const int mid = (l + r) / 2;
  ls[u] = build(l, mid);
  rs[u] = build(mid, r);
  return u;
}
int modify(int u, int l, int r, int pos, Value val) {
  if (!(l <= pos && pos < r)) return u;
  const int v = newNode();
  if (l + 1 == r) {
    vals[v] = val;
    return v;
  }
  const int mid = (l + r) / 2;
  ls[v] = modify(ls[u], l, mid, pos, val);
  rs[v] = modify(rs[u], mid, r, pos, val);
  vals[v] = vals[ls[v]] + vals[rs[v]];
  return v;
}
int modify(int u, int pos, Value val) {
  return modify(u, 0, n, pos, val);
}
Value get(int u, int l, int r, int a, int b) {
  if (b <= l || r <= a) return 0;
  if (a <= l && r <= b) return vals[u];
  const int mid = (l + r) / 2;
  return get(ls[u], l, mid, a, b) + get(rs[u], mid, r, a, b);
}
Value get(int u, int a, int b) {
  return get(u, 0, n, a, b);
}

// min pos s.t. (sum of [0, pos] in v) - (sum of [0, pos] in u) >= tar
int findRight(int u, int v, int l, int r, Value tar) {
  if (l + 1 == r) return r;
  const int mid = (l + r) / 2;
  const Value sumL = vals[ls[v]] - vals[ls[u]];
  return (sumL >= tar) ? findRight(ls[u], ls[v], l, mid, tar) : findRight(rs[u], rs[v], mid, r, tar - sumL);
}
int findRight(int u, int v, Value tar) {
  if (vals[v] - vals[u] < tar) return n + 1;
  return findRight(u, v, 0, n, tar);
}
}  // seg


Int sum1(Int n) {
  return n * (n + 1) / 2;
}

int N;
char S[500'010];
int Q;
vector<Int> K;

int main() {
  for (; ~scanf("%s", S); ) {
    N = strlen(S);
    scanf("%d", &Q);
    K.resize(Q);
    for (int q = 0; q < Q; ++q) {
      scanf("%lld", &K[q]);
      --K[q];
    }
    
    const SuffixTree st(S, false);
// cerr<<"graph = "<<st.graph<<endl;
// cerr<<"dis = "<<st.dis<<endl;
// cerr<<"fin = "<<st.fin<<endl;
// cerr<<"sid = "<<st.sid<<endl;
    // # occ
    vector<Int> dp(st.m, 0);
    vector<int> fin(st.m, 0);
    for (int i = 0; i < N; ++i) ++dp[st.dis[i]];
    for (int j = st.m; --j; ) dp[st.parJ(j)] += dp[j];
    vector<Int> ks(st.m + 1, 0);
    for (int j = 1; j < st.m; ++j) {
      const int u = st.sid[j];
      ks[j + 1] = ks[j] + dp[j] * (sum1(st[u].len) - sum1(st[st[u].par].len));
    }
// cerr<<"dp = "<<dp<<endl;
// cerr<<"ks = "<<ks<<endl;
    
    seg::init(N);
    vector<int> segs(st.m + 1);
    segs[0] = seg::build(0, N);
    for (int j = 0; j < st.m; ++j) {
      const int u = st.sid[j];
      segs[j + 1] = (u < N) ? seg::modify(segs[j], u, 1) : segs[j];
    }
    
    for (int q = 0; q < Q; ++q) {
      const int j = upper_bound(ks.begin(), ks.end(), K[q]) - ks.begin() - 1;
      const int u = st.sid[j];
      Int lo = st[st[u].par].len, hi = st[u].len;
      const Int s0 = sum1(lo);
      for (; lo + 1 < hi; ) {
        const Int mid = (lo + hi) / 2;
        ((ks[j] + (sum1(mid) - s0) <= K[q]) ? lo : hi) = mid;
      }
      const Int tar = K[q] - (ks[j] + (sum1(lo) - s0));
      const Int quo = tar / hi;
      const Int rem = tar % hi;
// cerr<<"K[q] = "<<K[q]<<": j = "<<j<<", hi = "<<hi<<", quo = "<<quo<<", rem = "<<rem<<endl;
      assert(0 <= quo); assert(quo < dp[j]);
      Int ans = seg::findRight(segs[st.dis[u]], segs[st.fin[u]], quo + 1) - 1;
      ans += rem;
      printf("%lld\n", ans + 1);
    }
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 7912kb

input:

pbpbppb
3
1
2
3

output:

2
4
7

result:

ok 3 lines

Test #2:

score: 0
Accepted
time: 1ms
memory: 7940kb

input:

potatop
3
6
30
60

output:

6
3
4

result:

ok 3 lines

Test #3:

score: 0
Accepted
time: 130ms
memory: 11668kb

input:

dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd...

output:

323
644
809
442
923
155
645
275
443
779
441
563
830
495
442
71
699
649
467
204
755
274
394
316
604
211
503
455
764
515
691
541
76
369
695
734
953
440
322
808
693
690
565
116
420
861
179
358
640
687
735
796
581
473
593
859
876
666
596
587
515
616
58
425
470
707
556
735
194
789
819
788
582
666
525
270...

result:

ok 500000 lines

Test #4:

score: -100
Runtime Error

input:

gtgggtgttgggggtgtgggtgttggtttggggtggtgtgggttggtggggtgggttgttggttgggtttggggtgttgggggtgggttttggttgttggtggggttgttggtggtggggtgggttttgggttggtgggtgggtggttgtgttggttttttttgttgggtttgggtgttgttgtggtgggttttggttggggtgttggttggtgtggtgtgggttttggttttttgtttgtggtggtgttttgtttttggtggggtgtttgttgttttggggttggggtgggggttgtgg...

output:

791
715
455
614
589
333
462
296
719
129
801
506
651
668
60
784
111
326
964
356
442
261
328
390
482
320
382
555
729
612
819
154
591
442
890
652
359
652
832
676
670
359
575
146
304
402
71
626
510
209
601
705
29
722
579
502
904
229
712
76
940
897
403
810
506
832
422
183
365
648
659
344
621
478
268
605
...

result: