1083B -编码树

https://codeforces.com/problemset/problem/1083/B

题目大意:给两个长度为n(len<=5e5)的只含有a和b的串S和串T,S<=T

于是存在字符串p使得S<=p<=T,从中任意选出k(k<=5e5)个字符串p

于是存在字符串s,使得s是k个字符串p之一的前缀

求有策略地选择k个字符串p,可使得符合条件的s数量最大的最大数量。

 

嗯~~~,刚开始想呀想,这种编码的东西真是不会呀。

后来看到cf上大神的超简单的代码(后面会给出),震惊了,

看半天终于看懂了,这样理解,以下的例子是S="aaa",T="bab"

这样的一棵树大家应该还是看得懂,字符串S和T就这样表示出来了

那么对于可行的字符串p,就是从S和T表示的路径的中间区域,向下走就可以了,走白色的点或者绿色的点

都OK,那么从图中可以看出,绿色的点有6个,白色的点(除根节点)有5个,因此字符串p的选择也有(6+5)=11个

接下来看到要求的答案,由于字符串p最多只能选择k个,并且由于如果A和B都可作字符串p,A是B的前缀,则B肯定不必A次

多以我们p的选择肯定是尽量长的。而当我们把k条p在树上用路径表示出来时,他们可获得的s数量也就是这些p中包含的结点数量。

知道了这些,接下来就是要遍历处理了

先看第一层,这一层的S,T子串是"a","b",这一层在两个绿点之间的白点数为rom=0,串p可以选择min(k,rom+2=2)个

下一层,S,T分别为“aa","ba",S和T的第二个字母都是'a',但白色节点还是增加了一个,所以rom固定要+1,p可以选择rom+2=3个

再下一层,上一层的白点分裂成了两个,由于S和T第三个字母分别是'a'和'b',白点又增加了1+1=2个,所以rom=rom*2+1+T[i]-S[i],这一层rom=4,p可选择min(k,rom+2=6)个

 

说了这么多,ans呢,ans我们也可以一层一层算,每一层可以是前缀的串s数量=min(k,rom+2)个

全部加起来ans就出来了

弄到树上好像的确简单好多了

	/
	while (++times, T--)
	{
		ll rom(0), ans(0);
		string s1, s2;
		ll n, k;
		cin >>n>>k >> s1 >> s2;
		RE(i, s1.length())
		{
			rom =  2*rom + s2[i] - s1[i];
			rom = min(rom, k);
			ans += min(rom+1,k);
		}
		cout << ans << endl;
	}
	///
	return 0;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值