题意

求一段区间内最大字母出现次数-最小字母出现次数的最大值。

题解

考虑BZOJ 2213: [Poi2011]Difference (DP)_#include代表当前字符BZOJ 2213: [Poi2011]Difference (DP)_c++_02减去字符BZOJ 2213: [Poi2011]Difference (DP)_#include_03的个数…

那么答案为BZOJ 2213: [Poi2011]Difference (DP)_#include_04

当右端点从BZOJ 2213: [Poi2011]Difference (DP)_#pragma_05变为BZOJ 2213: [Poi2011]Difference (DP)_#include_06的时候最多改变BZOJ 2213: [Poi2011]Difference (DP)_#include_07个值,所以暴力更新,同时维护最小的BZOJ 2213: [Poi2011]Difference (DP)_#include和次小的BZOJ 2213: [Poi2011]Difference (DP)_#include。注意求答案的时候要保证这段区间内最小字母出现次数不为BZOJ 2213: [Poi2011]Difference (DP)_c++_10

CODE

#pragma GCC optimize ("O2")
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
const int MAXM = 30;
int n, ans, tot[MAXM], cnt[MAXM][MAXM], Min[2][MAXM][MAXM], val[2][MAXM][MAXM];
char s[MAXN];
inline void upd(int i, int j) {
if(tot[j] != val[0][i][j]) ans = max(ans, cnt[i][j] - Min[0][i][j]);
else if(tot[j] != val[1][i][j]) ans = max(ans, cnt[i][j] - Min[1][i][j]);

if(cnt[i][j] < Min[0][i][j] && val[0][i][j] != tot[j]) {
Min[1][i][j] = Min[0][i][j], val[1][i][j] = val[0][i][j];
Min[0][i][j] = cnt[i][j], val[0][i][j] = tot[j];
}
else if(cnt[i][j] < Min[0][i][j]) {
Min[0][i][j] = cnt[i][j];
}
else if(cnt[i][j] < Min[1][i][j] && val[0][i][j] != tot[j]) {
Min[1][i][j] = cnt[i][j], val[1][i][j] = tot[j];
}
}
int main () {
scanf("%d%s", &n, s);
for(int i = 0, k, j; i < n; ++i)
for(++tot[k = s[i]-'a'], j = 0; j < 26; ++j)
if(j != k) {
++cnt[k][j], upd(k, j);
--cnt[j][k], upd(j, k);
}
printf("%d\n", ans);
}