Submission #1076904

#TimeUsernameProblemLanguageResultExecution timeMemory
1076904jcelinPalinilap (COI16_palinilap)C++14
100 / 100
195 ms43940 KiB
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define ll long long #define all(x) (x).begin(), (x).end() const int MOD = 1e9 + 7, mxn = 1e5 + 10; ll n, a[mxn]; struct SegmentTree { vector<ll> sum; vector<pair<ll, ll>> lz; SegmentTree(int n) { sum.resize(4 * n); lz.resize(4 * n); } void push(int k, int l, int r) { if (lz[k].second) { ll sz = (r - l + 1); sum[k] += lz[k].first * sz; sum[k] += lz[k].second * (sz * (sz + 1) / 2); if (l != r) { lz[k * 2].first += lz[k].first; lz[k * 2].second += lz[k].second; ll mid = (l + r) / 2; lz[k * 2 + 1].first += lz[k].first + lz[k].second * (mid - l + 1); lz[k * 2 + 1].second += lz[k].second; } lz[k] = {0, 0}; } } void update(int k, int l, int r, int i, int j) { if (l > j || r < i) return; if (i <= l && r <= j) { lz[k].first += l - i; lz[k].second += 1; push(k, l, r); return; } int mid = (l + r) / 2; update(k * 2, l, mid, i, j); update(k * 2 + 1, mid + 1, r, i, j); } void get(int k, int l, int r, bool d) { push(k, l, r); if (l == r) { if (d) a[l] += sum[k]; else a[n - l - 1] += sum[k]; return; } int mid = (l + r) / 2; get(k * 2, l, mid, d); get(k * 2 + 1, mid + 1, r, d); } } sgtF(mxn), sgtB(mxn); ll expo(ll a, ll b, ll mod) { a %= mod; ll res = 1; while (b) { if (b % 2 == 1) res = (res * a) % mod; a = (a * a) % mod; b /= 2; } return res; } ll fact[mxn + 1], inv[mxn + 1], inv29 = expo(29, MOD - 2, MOD); void precalc() { inv[0] = expo(1, MOD - 2, MOD); for (int i = 1; i <= mxn; i++) inv[i] = (inv[i - 1] * inv29) % MOD; } string s; ll prf[mxn], suf[mxn], F[mxn], change[mxn][26]; ll getPRF(int l, int r) { ll num = prf[r] - (l ? prf[l - 1] : 0); num = (num + MOD) % MOD; num = (num * inv[l]) % MOD; return num; } ll getSUF(int l, int r) { ll num = suf[l] - (r < n - 1 ? suf[r + 1] : 0); num = (num + MOD) % MOD; num = (num * inv[n - 1 - r]) % MOD; return num; } bool same(int l1, int r1, int l2, int r2) { if (l1 < 0 || r1 >= n || l2 < 0 || r2 >= n) return 0; return getPRF(l1, r1) == getSUF(l2, r2); } ll solve(ll i, int startL = -1000, int startR = -1000) { int sl = i / 2, sr = i / 2; if (i % 2 != 0) sr = i / 2 + 1; if (startL != -1000) { sl = startL; sr = startR; } if (sl < 0 || sr >= n) return 0; int l = 0, r = min(i / 2, n - i / 2) + 2; while (l + 1 < r) { int mid = (l + r) / 2; if (same(sl - mid, sl, sr, sr + mid)) l = mid; else r = mid; } return l; } void updateF(int l, int r) { if (l > r) return; sgtF.update(1, 0, n - 1, l, r); } void updateB(int l, int r) { if (n - r - 1 > n - l - 1) return; sgtB.update(1, 0, n - 1, n - r - 1, n - l - 1); } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); precalc(); cin >> s; n = s.size(); F[0] = 1; for (int i = 1; i <= n; i++) F[i] = (F[i - 1] * 29) % MOD; for (int i = 0; i < n; i++) { if (i) prf[i] = prf[i - 1]; prf[i] = (prf[i] + (s[i] - 'a') * F[i]) % MOD; } for (int i = n - 1; i >= 0; i--) { if (i < n - 1) suf[i] = suf[i + 1]; suf[i] = (suf[i] + (s[i] - 'a') * F[n - 1 - i]) % MOD; } ll ans = 0; for (int i = 0; i < 2 * n - 1; i++) { int sl = i / 2, sr = i / 2; if (i % 2 != 0) sr = i / 2 + 1; ll add = s[sl] == s[sr]; ll lp = solve(i) + add; int LR = sl - (lp - 1), RR = sr + (lp - 1); ans += lp; if (LR != RR) { updateF(LR, sl - (i % 2 == 0)); updateB(sr + (sl == sr), RR); } int L = sl - lp, R = sr + lp; if (L < 0 || R > n - 1) continue; ll newLp = solve(i, L - 1, R + 1); if (L - 1 - newLp >= 0 && R + 1 + newLp < n && s[L - 1 - newLp] == s[R + 1 + newLp]) add = 1; else add = 0; change[L][s[R] - 'a'] += newLp + 1 + add; newLp = solve(i, L - 1, R + 1); if (L - 1 - newLp >= 0 && R + 1 + newLp < n && s[L - 1 - newLp] == s[R + 1 + newLp]) add = 1; else add = 0; change[R][s[L] - 'a'] += newLp + 1 + add; } sgtF.get(1, 0, n - 1, 1); sgtB.get(1, 0, n - 1, 0); ll mx = 0; for (int i = 0; i < n; i++) { ll best = 0; for (int j = 0; j < 26; j++) best = max(best, change[i][j]); mx = max(mx, best - a[i]); } cout << ans + mx; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...