D. Trees and Segments

l0:最大连续0的个数,l1:最大连续1的个数

题目要求a*l0+l1的值最大

可以翻转k次操作

我们知道最大的连续0和最大连续1之间一定会有间隔

比如:0111111010000000000

前7位最大连续1的个数位6个,你的最大连续0的个数就一定要在第8位后面去找

于是我们可以用一个dp函数去找

dp[i][j]表示前i位翻转j次出现连续最大1的最大次数

dp2[i][j]表示后i位翻转j次出现连续0的最大次数

于是我们就可以知道当你要求前i位翻转j(j<=k)次时最大1的次数,你要找到最大0的次数就是在dp2[m-i][k-j]就是后m-i位翻转k-j次最大0的次数

然后再做一遍dp

dp[i][j]表示前i位翻转j次     最大0的次数

dp2[i][j]表示后i位翻转j次   最大1的次数

根据上面再做一遍

如果你开一个best[i]表示当你l1取i时你l0最大是多少,当然越大越好

#include
#include
#include//accumulate(be,en,0)
#include//rfind("string"),s.find(string,begin)!=s.npos,find_first _of(),find_last_of()
#include//to_string(value),s.substr(int begin, int length);
#include
#include
#include//res.erase(unique(res.begin(), res.end()), res.end()),reverse(q.begin(),q.end()),vector().swap(at[mx])
#include//priority_queue(big)  /priority_queue, greater> q(small)
#include
//#include//unordered_map
#include//iterator,insert(),erase(),lower(>=)/upper_bound(>)(value)/find()return end()
#include
#include
#include//size,count(size of 1),reset(to 0),any(have 1?)
//#include//gp_hash_table
//#include
//using namespace __gnu_pbds;
#define int long long//__int128 2^127-1(GCC)
#define PII pair
using namespace std;
const int inf = 0x3f3f3f3f3f3f3f3f, N = 1e5 + 5, mod = 1e9 + 7;
vector>calc(string& s, char c)
{
	int n = s.size();
	vector>ans;
	vectorcur(n + 1, 0);
	vectorpos;
	pos.emplace_back(-1);
	for (int i = 0; i < n; i++) {
		ans.emplace_back(cur);
		if (s[i] == c) pos.emplace_back(i);
		int m = pos.size();
		for(int j = 0; j < m; j++) {
			cur[m - j - 1] = max(cur[m - j - 1], i - pos[j]);
		}
		for (int i = 1; i <= n; i++) cur[i] = max(cur[i], cur[i - 1]);
	}
	ans.emplace_back(cur);
	return ans;
}
signed main()
{
	ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--)
	{
		int n, k;
		cin >> n >> k;
		string s;
		cin >> s;
		vectorbest(n + 1, -100000);
		for (int z : {0, 1}) {
			vector>dp = calc(s, '0');
			reverse(s.begin(), s.end());
			vector>dp2 = calc(s, '1');
			reverse(dp2.begin(), dp2.end());
			for (int i = 0; i <= n; i++) {
				for (int j = 0; j <= k; j++) {
					best[dp[i][j]] = max(best[dp[i][j]], dp2[i][k - j]);
				}
			}
		}
		for (int i = 1; i <= n; i++) {
			int ans = 0;
			for (int j = 0; j <= n; j++) {
				ans = max(ans, i * best[j] + j);
			}
			cout << ans << ' ';
		}
		cout << '\n';
	}
}

你可能感兴趣的:(算法)