【贪心/Trie】【CF1083B】 The Fair Nut and Strings

Description

\(k\) 个长度为 \(n\) 的只含 \(a\)\(b\) 字符串,并不知道它们具体是多少,只知道它们的字典序不小于字符串 \(A\),同时不大于字符串 \(B\)。定义一个字符串是合法的当且仅当它是这 \(k\) 个字符串之一的前缀(如果它是多个串的前缀那么只计算一次)。求合法的字符串最大可能是多少

Input

第一行是两个整数 \(n\)\(k\)

下面两行,第一行是长度为 \(n\) 的字符串 \(A\),第二行是长度为 \(n\) 的字符串 \(B\)

Output

输出一个数代表答案。

Hint

\(1~\leq~n~\leq~5~\times~10^5~,~1~\leq~k~\leq~10^9\)

Solution

我们考虑假如对这 \(k\) 个字符串建出一棵Trie树,那么显然一个节点对应一个合法的字符串,答案即为树上节点个数。于是我们的问题即被转化为了最大化Trie树上的节点个数。考虑在一个节点,在合法的条件下孩子数为 \(2\) 的答案显然不劣于孩子数为 \(1\) 的答案。于是我们依照此按照层数进行贪心,尽可能的多分节点即可。考虑因为最后一层的节点最多有 \(k\) 个,所以当算到一层的节点数不小于 \(k\) 时,后面就无需枚举,直接分配给每层 \(k\) 个节点计算答案即可。

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long

typedef long long int ll;

namespace IPT {
	const int L = 1000000;
	char buf[L], *front=buf, *end=buf;
	char GetChar() {
		if (front == end) {
			end = buf + fread(front = buf, 1, L, stdin);
			if (front == end) return -1;
		}
		return *(front++);
	}
}

template <typename T>
inline void qr(T &x) {
	rg char ch = IPT::GetChar(), lst = ' ';
	while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
	while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
	if (lst == '-') x = -x;
}

template <typename T>
inline void ReadDb(T &x) {
	rg char ch = IPT::GetChar(), lst = ' ';
	while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
	while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
	if (ch == '.') {
		ch = IPT::GetChar();
		double base = 1;
		while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
	}
	if (lst == '-') x = -x;
}

namespace OPT {
	char buf[120];
}

template <typename T>
inline void qw(T x, const char aft, const bool pt) {
	if (x < 0) {x = -x, putchar('-');}
	rg int top=0;
	do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
	while (top) putchar(OPT::buf[top--]);
	if (pt) putchar(aft);
}

const int maxn = 500010;

ll n, k, ans;
char MU[maxn], CU[maxn];

int main() {
	freopen("1.in", "r", stdin);
	qr(n); qr(k);
	do MU[1] = IPT::GetChar(); while ((MU[1] > 'z') || (MU[1] < 'a'));
	for (rg int i = 2; i <= n; ++i) MU[i] = IPT::GetChar();
	do CU[1] = IPT::GetChar(); while ((CU[1] > 'z') || (CU[1] < 'a'));
	for (rg int i = 2; i <= n; ++i) CU[i] = IPT::GetChar();
	ll pre = 1;
	for (rg int i = 1; i <= n; ++i) {
		pre <<= 1;
		if (MU[i] == 'b') --pre;
		if (CU[i] == 'a') --pre;
		if (pre >= k) {
			ans += 1ll * k * (n - i + 1);
			break;
		}
		ans += pre;
	}
	qw(ans, '\n', true);
	return 0;
}
posted @ 2019-01-07 20:05  一扶苏一  阅读(321)  评论(0编辑  收藏  举报