結果

問題 No.515 典型LCP
ユーザー nohtaraynohtaray
提出日時 2019-10-05 14:11:29
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 551 ms / 1,000 ms
コード長 4,045 bytes
コンパイル時間 3,410 ms
コンパイル使用メモリ 204,708 KB
実行使用メモリ 100,280 KB
最終ジャッジ日時 2024-04-15 18:33:46
合計ジャッジ時間 7,740 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 537 ms
100,020 KB
testcase_01 AC 551 ms
100,280 KB
testcase_02 AC 155 ms
71,020 KB
testcase_03 AC 2 ms
6,940 KB
testcase_04 AC 2 ms
6,940 KB
testcase_05 AC 126 ms
71,652 KB
testcase_06 AC 131 ms
70,808 KB
testcase_07 AC 132 ms
71,384 KB
testcase_08 AC 142 ms
71,280 KB
testcase_09 AC 132 ms
71,172 KB
testcase_10 AC 141 ms
70,248 KB
testcase_11 AC 141 ms
71,288 KB
testcase_12 AC 138 ms
71,536 KB
testcase_13 AC 142 ms
70,664 KB
testcase_14 AC 8 ms
6,940 KB
testcase_15 AC 130 ms
71,172 KB
testcase_16 AC 127 ms
70,508 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

#ifdef DEBUG
#include "libs/debug.cpp"
#define DEBUG 1
#else
#define DEBUG 0
#endif

#define rep(i, n) repr((i), 0, (n))
#define repr(i, a, t) reps((i), (a), (t), 1)
#define reps(i, a, t, s) for (long long (i) = (a); (i) < (long long)(t); (i) += (s))
#define rrep(i, n) rrepr((i), (n) - 1, 0)
#define rrepr(i, a, t) rreps((i), (a), (t), 1)
#define rreps(i, a, t, s) for (long long (i) = (a); (i) >= (long long)(t); (i) -= (s))
#define each(v, c) for (auto &&(v) : (c))
#define all(c) (c).begin(), (c).end()

using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
template<typename T>
const long long MOD = 1e9 + 7;
const long long INF = 1e18;

/**
 * 構築 O(NlogN)、クエリ O(1)
 * @tparam T
 */
template<typename T>
class SparseTable {
 private:
  vector<T> values;
  vector<vector<unsigned long>> table;
  vector<unsigned long> msb;
  function<T(T, T)> fn;

  static vector<vector<unsigned long >> build(const vector<T> &values, function<T(T, T)> fn) {
    unsigned long size = (unsigned long) log2(values.size()) + 1;

    vector<vector<unsigned long >> st(values.size(), vector<unsigned long>(size));
    for (unsigned long i = 0; i < values.size(); ++i) st[i][0] = i;
    for (unsigned long p = 1; p < size; ++p) {
      for (unsigned long i = 0; i < values.size(); ++i) {
        unsigned long q = min(i + (1 << (p - 1)), (unsigned long) values.size() - 1);
        unsigned long l = st[i][p - 1];
        unsigned long r = st[q][p - 1];
        if (values[l] == fn(values[l], values[r])) {
          st[i][p] = l;
        } else {
          st[i][p] = r;
        }
      }
    }
    return st;
  }

 public:
  SparseTable(const vector<T> &values, function<T(T, T)> fn) {
    this->values = values;
    this->fn = fn;

    // table[i][p]: [i, i + 2^p) に fn を適用した結果の値のインデックス
    table = build(values, fn);

    // msb[i]: 最上位ビット; どの p を見るべきか
    msb = vector<unsigned long>(values.size() + 1);
    for (unsigned long i = 2; i < values.size() + 1; ++i) {
      msb[i] = msb[i >> 1] + 1;
    }
  }

  /**
   * [a, b) に fn を適用した結果
   */
  T get(unsigned long a, unsigned long b) {
    if (b <= a) throw invalid_argument("a < b でないといけません");
    if (b > values.size()) throw invalid_argument("範囲外です");
    unsigned long p = msb[b - a];
    return fn(values[table[a][p]], values[table[b - (1 << p)][p]]);
  }
};

template<typename T>
vector<unsigned long> argsort(const vector<T> &vec) {
  vector<pair<T, unsigned long>> values;
  vector<unsigned long> ret;

  for (unsigned long i = 0; i < vec.size(); ++i) values.emplace_back(vec[i], i);
  sort(values.begin(), values.end());
  for (const auto &item: values) ret.push_back(item.second);
  return ret;
}

vector<pair<ll, ll>> genq(ll N, ll M, ll X, ll D) {
  vector<pair<ll, ll>> ret;
  repr (k, 1, M + 1) {
    ll i, j;
    i = (X / (N - 1)) + 1;
    j = (X % (N - 1)) + 1;
    if (i > j) swap(i, j);
    else j++;
    ret.emplace_back(i, j);
    X = (X + D) % (N * (N - 1));
  }
  return ret;
}

int main() {
  cout << fixed << setprecision(10);
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  ifstream ifs;
  if (DEBUG) {
    ifs.open("src/_in.txt");
    cin.rdbuf(ifs.rdbuf());
  }

  ll N;
  cin >> N;
  vector<string> S;
  rep (i, N) {
    string v0;
    cin >> v0;
    S.push_back(v0);
  }
  ll M, X, D;
  cin >> M >> X >> D;

  auto idx = argsort(argsort(S));
  sort(all(S));

  // lcp[i]: S[i] と S[i + 1] の共通接頭辞の長さ
  vector<ll> lcp(N - 1);
  rep (i, N - 1) {
    ll j = 0;
    while (j < S[i].size() && j < S[i + 1].size() && S[i][j] == S[i + 1][j]) ++j;
    lcp[i] = j;
  }

  auto st = SparseTable<ll>(lcp, [](ll a, ll b) { return min(a, b); });

  ll ans = 0;
  auto queries = genq(N, M, X, D);
  each (query, queries) {
    ll i, j;
    tie(i, j) = query;
    i = idx[i - 1];
    j = idx[j - 1];
    if (i > j) swap(i, j);
    ans += st.get(i, j);
  }
  cout << ans << "\n";
}
0