题目链接:
http://codeforces.com/contest/676/problem/C
题解:
把连续的一段压缩成一个数,对新的数组求前缀和,用两个指针从左到右线性扫一遍。
一段值改变一部分的情况考虑的不够周到,wa了两次。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> using namespace std; const int maxn = 100000 + 10; char str[maxn]; int arr[maxn], tot; int sum[maxn]; int n, k; int solve(int fst) { int ret = -1, cnt = 0; int p1 = fst; for (int p2 = fst; p2 <= tot; p2 += 2) { cnt += arr[p2]; while (p1 <= p2&&cnt > k) { cnt -= arr[p1]; p1 += 2; } if (p1 <= p2) { if (p1 - 2 >= 0 && p2 + 1 <= n) { ret = max(ret, sum[p2 + 1] - sum[p1 - 2]+k-cnt); ret = min(ret, n); } else if (p1 - 2 >= 0) { ret = max(ret, sum[p2] - sum[p1 - 2] + k - cnt); ret = min(ret, n); } else if (p2 + 1 <= n) { ret = max(ret, sum[p2 + 1] - sum[p1 - 1] + k - cnt); ret = min(ret, n); } else { ret = max(ret, sum[p2] - sum[p1 - 1] + k - cnt); ret = min(ret, n); } } } return ret; } int main() { while (scanf("%d%d", &n, &k) == 2 && n) { scanf("%s", str); tot = 0; int cnt = 1; for (int i = 0; i < n - 1; i++) { if (str[i] != str[i + 1]) { arr[++tot] = cnt; cnt = 1; } else { cnt++; } } arr[++tot] = cnt; sum[0] = 0; for (int i = 1; i <= tot; i++) sum[i] = sum[i - 1] + arr[i]; int ans = 0; for (int i = 1; i <= tot; i++) { ans = max(ans, arr[i] + k); ans = min(ans, n); } ans = max(ans, solve(1)); ans = max(ans, solve(2)); printf("%d ", ans); } return 0; } /* 4 2 abba 8 1 aabaabaa 5 2 ababa 5 1 ababa 4 1 aaba 5 0 aaaaa */