Submission #617277

# Submission time Handle Problem Language Result Execution time Memory
617277 2022-08-01T10:23:39 Z maximath_1 Palinilap (COI16_palinilap) C++11
54 / 100
156 ms 19800 KB
#include <bits/stdc++.h>
using namespace std;

#define ll long long
const int MX = 1e5 + 5;
const ll mod = 420691273;
const ll mod2 = 1e9 + 9;
const ll pp = 37;
const ll pp2 = 31;

string s, sr;
int n;
ll pwp[MX][2], ipwp[MX][2], hsh[MX][2], hshr[MX][2];

ll pw(ll b, ll e, ll m){
	ll r = 1ll; b %= m;
	for(; e > 0; e /= 2, (b *= b) %= m)
		if(e % 2) (r *= b) %= m;
	return r;
}

bool check_palindrome(int lf, int cl, int cr, int rg){
	rg = n - 1 - rg; cr = n - 1 - cr;
	if(lf > cl || rg > cr || lf < 0 || rg < 0) return 0;

	bool ok = 1;
	for(int i = 0; i < 2; i ++){
		ll hashL = hsh[cl][i] - (lf == 0 ? 0 : hsh[lf - 1][i]); if(hashL < 0) hashL += (i ? mod2 : mod);
		(hashL *= ipwp[lf][i]) %= (i ? mod2 : mod);
		ll hashR = hshr[cr][i] - (rg == 0 ? 0 : hshr[rg - 1][i]); if(hashR < 0) hashR += (i ? mod2 : mod);
		(hashR *= ipwp[rg][i]) %= (i ? mod2 : mod);
		ok &= (hashL == hashR);
	}

	return ok;
}

int add[MX][30]; // change s[i] to j + 'a', how many palindromes are added
int delRunning[MX]; ll delCap[MX];
/*
 a  b  c  d  d  c  b  a   |  a  b  c  b  a
 1  2  3  4  4  3  2  1   |  1  2  0  2  1
changing s[i] will delete palindromes according to above
for left side, represent as i - x, x constant (delRuuning = 1, delCap = -x)
for right, represent as x - i, x constant (delRunning = -1, delCap = x)
when added, will become in the form of i * delRunning + delCap
is range update point query, with all queries processed at the end -> offline prefix difference
*/

int main(){
	cin >> s;
	sr = s; reverse(sr.begin(),sr.end());
	n = s.size();

	pwp[0][0] = 1;
	for(int i = 1; i < MX; i ++)
		pwp[i][0] = (pwp[i - 1][0] * 1ll * pp) % mod;
	ipwp[MX - 1][0] = pw(pwp[MX - 1][0], mod - 2, mod);
	for(int i = MX - 2; i >= 0; i --)
		ipwp[i][0] = (ipwp[i + 1][0] * 1ll * pp) % mod;
	pwp[0][1] = 1;
	for(int i = 1; i < MX; i ++)
		pwp[i][1] = (pwp[i - 1][1] * 1ll * pp2) % mod2;
	ipwp[MX - 1][1] = pw(pwp[MX - 1][1], mod2 - 2, mod2);
	for(int i = MX - 2; i >= 0; i --)
		ipwp[i][1] = (ipwp[i + 1][1] * 1ll * pp2) % mod2;

	for(int i = 0; i < n; i ++){
		for(int j = 0; j < 2; j ++){
			hsh[i][j] = (pwp[i][j] * 1ll * (s[i] - 'a')) % (j ? mod2 : mod);
			hshr[i][j] = (pwp[i][j] * 1ll * (sr[i] - 'a')) % (j ? mod2 : mod);

			if(i > 0){
				hsh[i][j] += hsh[i - 1][j]; if(hsh[i][j] >= (j ? mod2 : mod)) hsh[i][j] -= (j ? mod2 : mod);
				hshr[i][j] += hshr[i - 1][j]; if(hshr[i][j] >= (j ? mod2 : mod)) hshr[i][j] -= (j ? mod2 : mod);
			}
		}
	}

	ll base_answer = 0ll;
	for(int cl = 0; cl < n; cl ++){
		for(int cr = cl; cr <= cl + 1; cr ++){
			int lf = 0, rg = min(cl + 1, n - cr), rs = lf;
			for(int md; lf <= rg;){
				md = (lf + rg + 1) / 2;
				if(check_palindrome(cl - md + 1, cl, cr, cr + md - 1)){
					rs = md;
					lf = md + 1;
				}else{
					rg = md - 1;
				}
			}
			base_answer += rs;

			// process deleting
			if(cl == cr){
				// odd case
				delRunning[cl - rs + 1] ++; delRunning[cl] --; // left side
				delCap[cl - rs + 1] -= cl - rs; delCap[cl] += cl - rs;

				delRunning[cr + 1] --; delRunning[cr + rs] ++; // right side
				delCap[cr + 1] += cr + rs; delCap[cr + rs] -= cr + rs;
			}else{
				// even case
				delRunning[cl - rs + 1] ++; delRunning[cl + 1] --; // left side
				delCap[cl - rs + 1] -= cl - rs; delCap[cl + 1] += cl - rs;

				delRunning[cr] --; delRunning[cr + rs] ++; // right side
				delCap[cr] += cr + rs; delCap[cr + rs] -= cr + rs;
			}

			// process adding
			int xl = cl - rs, xr = cr + rs; rs ++;
			if(xl < 0 || xr >= n) continue;
			lf = 0, rg = min(cl + 1, n - cr) - rs; rs = lf;
			for(int md; lf <= rg;){
				md = (lf + rg + 1) / 2;
				if(check_palindrome(xl - md, xl - 1, xr + 1, xr + md)){
					rs = md;
					lf = md + 1;
				}else{
					rg = md - 1;
				}
			}

			add[xl][s[xr] - 'a'] += rs + 1;
			add[xr][s[xl] - 'a'] += rs + 1;
		}
	}

	ll best_change = 0ll;
	ll run = 0ll, cap = 0ll;
	for(int i = 0; i < n; i ++){
		run += delRunning[i];
		cap += delCap[i];
		for(int j = 0; j < 26; j ++) if(s[i] - 'a' != j){
			best_change = max(best_change, add[i][j] - (run * 1ll * i + cap));
		}
	}

	cout << base_answer + best_change << endl;
	return 0;
}
# Verdict Execution time Memory Grader output
1 Correct 3 ms 3412 KB Output is correct
2 Correct 3 ms 3412 KB Output is correct
3 Correct 3 ms 3412 KB Output is correct
4 Correct 4 ms 3412 KB Output is correct
5 Correct 4 ms 3412 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 7 ms 4220 KB Output is correct
2 Correct 6 ms 4180 KB Output is correct
3 Correct 7 ms 4180 KB Output is correct
4 Correct 5 ms 3924 KB Output is correct
5 Correct 7 ms 4052 KB Output is correct
6 Correct 7 ms 4180 KB Output is correct
7 Correct 10 ms 4256 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 116 ms 19588 KB Output is correct
2 Correct 103 ms 19572 KB Output is correct
3 Correct 74 ms 19668 KB Output is correct
4 Correct 124 ms 19648 KB Output is correct
5 Correct 116 ms 19656 KB Output is correct
6 Correct 111 ms 19688 KB Output is correct
7 Correct 114 ms 19572 KB Output is correct
8 Correct 59 ms 7944 KB Output is correct
9 Correct 119 ms 19632 KB Output is correct
10 Correct 155 ms 19660 KB Output is correct
11 Correct 98 ms 19800 KB Output is correct
12 Correct 154 ms 19648 KB Output is correct
13 Correct 146 ms 19684 KB Output is correct
14 Correct 110 ms 19668 KB Output is correct
15 Correct 156 ms 19648 KB Output is correct
16 Incorrect 112 ms 19680 KB Output isn't correct
17 Halted 0 ms 0 KB -