1 条题解
-
0
今天联考T2,蒟蒻抢了最优解来水篇题解其实是蒟蒻的第一篇题解前置知识: 最大子段和。
由于字符集很小,只有 所以我们可以钦定最多出现次数的字符 与最少的字符 (注意 都必须是字符串中出现过的),将所有 赋值为 ,所有 赋值为 ,其余字符赋值为 ,求强制至少选一个 的最大字段和。
我们用 表示以钦定 为最多出现次数的字符, 为最少出现次数的字符的最大子段和。容易发现 的转移只与上一次的 和下一次的 出现的位置有关,于是可以直接滚动数组,从左往右枚举字符 ,并处理 与 的情况,剩下的一维则枚举。
记 。
更新为 表示一定会选当前这个 。
更新为 。
考虑如何强制至少选一个 :
我们用 表示当前选/没选至少一个 。则统计答案时记为 。
随 转移,当 时有 。
代码很好写:
#include <bits/stdc++.h> #define a s[i] using namespace std; int f[26][26], n, A, i, v[26]; bool h[26][26];char s[1000001]; vector<int> e; signed main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> s; for (i = 0; i < n; ++i) if (!v[a -= 'a']) { v[a] = 1; e.push_back(a);//记录出现过的字符集 } for (i = 0; i < n; ++i) for (int b : e) if (b ^ a) { ++f[a][b]; A = max(A, f[a][b] - !h[a][b]);//记录答案,如果没有选-1要减去1 h[b][a] = f[b][a];//h为bool类型 表示h[b][a]=[f[b][a]>=1],若上一次的f[b][a]不为0表示可选这个-1 f[b][a] = max(0, f[b][a] - 1); } cout << A; return 0; }时间复杂度 常数极小,跑了124ms。
- 1
信息
- ID
- 3878
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者