noip模拟赛 a
分析:其实就是要求sum[a][r] - sum[a][l - 1] - (sum[b][r] - sum[b][l - 1])最大,变形一下,可以得到sum[a][r] - sum[b][r] - (sum[a][l - 1] - sum[b][l - 1]),我们可以枚举位置r和b,a就是当前位置的字符,那么后面的(sum[a][l - 1] - sum[b][l - 1])我们可以在前面用一个数组记录一下最小值,这样扫一遍就能出答案.不过有一种特殊情况是sum[a][l - 1] - sum[b][l - 1]最小的位置可能和上一次b出现的位置冲突,因为一个位置上不可能出现2个字母,所以答案-1就可以了.
写出式子来要等价变形!把结构相同的放在一类,然后思考如何优化!
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n, last[1000010], f[30][30], sum[30], ans; int pos[30][30]; char s[1000010]; int main() { scanf("%d", &n); scanf("%s", s + 1); memset(f, 0x3f, sizeof(f)); for (int i = 1; i <= n; i++) { int p = s[i] - 'a'; sum[p]++; last[p] = i; for (int j = 0; j < 26; j++) if (p != j && sum[j]) ans = max(ans, max(sum[p] - sum[j] - f[p][j] - (last[j] == pos[p][j] ? 1 : 0), sum[j] - sum[p] - f[j][p] - (last[j] == pos[j][p] ? 1 : 0))); for (int j = 0; j < 26; j++) { if (sum[p] - sum[j] < f[p][j]) { f[p][j] = sum[p] - sum[j]; pos[p][j] = i; } if (sum[j] - sum[p] < f[j][p]) { f[j][p] = sum[j] - sum[p]; pos[j][p] = i; } } } printf("%d\n", ans); return 0; }