CodeForces 1841C Ranom Numbers
先反转 \(s\) 串,然后考虑 dp,设 \(f_{i, j, 0/1}\) 为考虑了 \([1, i]\),前缀最大值为 \(j\),是否修改过字符的最大得分。
转移讨论是否在这个位置修改即可。
时间复杂度 \(O(n)\)。
code
// Problem: C. Ranom Numbers
// Contest: Codeforces - Educational Codeforces Round 150 (Rated for Div. 2)
// URL: https://codeforces.com/group/bXwyZVR0kC/contest/1841/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 200100;
const int mp[] = {1, 10, 100, 1000, 10000};
int n, a[maxn];
ll f[maxn][5][2];
char s[maxn];
void solve() {
scanf("%s", s + 1);
n = strlen(s + 1);
reverse(s + 1, s + n + 1);
for (int i = 1; i <= n; ++i) {
a[i] = s[i] - 'A';
}
for (int i = 0; i <= n; ++i) {
for (int j = 0; j < 5; ++j) {
for (int k = 0; k < 2; ++k) {
f[i][j][k] = -1e18;
}
}
}
f[0][0][0] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < 5; ++j) {
for (int k = 0; k < 2; ++k) {
if (f[i - 1][j][k] < -1e17) {
continue;
}
if (j > a[i]) {
f[i][j][k] = max(f[i][j][k], f[i - 1][j][k] - mp[a[i]]);
} else {
f[i][a[i]][k] = max(f[i][a[i]][k], f[i - 1][j][k] + mp[a[i]]);
}
}
for (int k = 0; k < 5; ++k) {
if (f[i - 1][j][0] < -1e17) {
continue;
}
if (j > k) {
f[i][j][1] = max(f[i][j][1], f[i - 1][j][0] - mp[k]);
} else {
f[i][k][1] = max(f[i][k][1], f[i - 1][j][0] + mp[k]);
}
}
}
}
ll ans = -1e18;
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 2; ++j) {
ans = max(ans, f[n][i][j]);
}
}
printf("%lld\n", ans);
}
int main() {
int T = 1;
scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}