首页 > 其他分享 >【题解】Atcoder ABC300 F.More Holidays(线性做法)

【题解】Atcoder ABC300 F.More Holidays(线性做法)

时间:2023-06-18 09:00:40浏览次数:51  
标签:子串 Atcoder int 题解 ABC300 SS 端点 一段 More

F.More Holidays

题目描述:

给你一个由 ox 组成的长度为 \(N\) 的字符串 \(S\),以及整数 \(M\) 和 \(K\)。保证 \(S\) 至少包含一个 x

假设 \(T\) 是由 \(S\) 复制 \(M\) 次而成的长度为 \(NM\) 的字符串。考虑将 \(T\) 中的 \(K\) 个 x 恰好替换为 o

你的目标是在替换后的 \(T\) 中有尽可能长的由 o 组成的连续子串。

找出在替换后由 o 组成的连续子串的最大长度。

题目分析:

提供一种线性做法。

仿佛见过一道类似的题,不确定是不是就是这道。

考虑我们最后得到的极长连续的 o 串,一定是形如:(\(S\) 的一段后缀) + (若干个完整的 \(S\)) + (\(S\) 的一段前缀)

对于若干个完整的 \(S\) 我们可以直接求出来它的个数,设 \(tot\) 为 \(S\) 中 x 的个数则中间完整 \(S\) 的个数就是 \(\lfloor \frac{k}{tot} \rfloor\)

而对于 \(S\) 的一段后缀 + \(S\) 的一段前缀,我们可以考虑把他们拼在一起,也就是将 \(S\) 变成 \(SS\) 即二倍字符串长度,这样我们发现 \(SS\) 的任意一个子串都可以表示为上述形式,但是任意的上述形式就是 \(SS\) 的某一子串嘛?

其实不一定吧,因为我们上述的形式其实并不完整,因为我们可能连一整段都取不到所以可能最后取到的极长字串就是 \(S\) 内的一段区间,但是这样会发现虽然不完全,但是我们依旧可以对于 \(S\) 的每一个子串找到 \(SS\) 中的一个子串使得他们相等,所以就没有什么问题。

解决这个问题,一个想法就是直接枚举左端点,然后右端点就可以二分取得。

但是你会发现二分右端点是一个很傻的行为,因为随着左端点的增加右端点单调不降,所以可以直接使用双指针优化到 \(O(n)\)

需要注意的细节就是:有 \(m\) 个的限制所以可能我们没办法取得 (\(S\) 的一段后缀) + (\(S\) 的一段前缀)。

代码:

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6+5;
char s[N];
int pre[N];
signed main(){
	int n,m,k;scanf("%lld%lld%lld",&n,&m,&k);
	scanf("%s",s+1);
	for(int i=1; i<=n; i++)	s[i+n] = s[i];
	for(int i=1; i<=2 * n; i++)	pre[i] = pre[i-1] + (s[i] == 'x');
	int ans = k / pre[n] * n,tmp = 0;
	m -= k / pre[n];
	k = k % pre[n];
	for(int l=1,r = 1; l<=n; l++){
		while(r + 1 <= 2 * n && pre[r + 1] <= k + pre[l-1]) ++r;
		if(m == 1)	tmp = max(tmp,min(r,n) - l + 1);
		else if(m > 1)	tmp = max(tmp,r - l + 1);
	}
	printf("%lld\n",ans + tmp);
	return 0;
}

标签:子串,Atcoder,int,题解,ABC300,SS,端点,一段,More
From: https://www.cnblogs.com/linyihdfj/p/17488679.html

相关文章

  • P2161 [SHOI2009]会场预约 题解
    蒟蒻提供一种fhq-treap的做法,但是不如其他题解的快(也没有stl快,不开O21.8s),但是比较好想,扩展了fhq的模板,也算是为使用fhq提供一个新方法。首先,fhq-treap是什么,如果有同学不清楚,请点击学习(并非我的blog)那么,由于fhq树的分裂操作,使得我们可以很方便的取出我们想要的区间。那么,在......
  • AtCoder Beginner Contest 306
    A-Echo(abc306a)题目大意给定一个字符串,将每个字符输出两次。解题思路模拟即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);intn;......
  • react经典面试题解析--持续更新--day01
    一、类组件和函数组件的区别(面试常考)简单理解(所有同学都要掌握)1、类组件有生命周期,函数组件没有2、类组件需要继承Class,函数组件不需要3、类组件可以获取实例化的this,并且基于this做各种操作,函数组件不行4、类组件内部可以定义并维护state,函数组件都称为无状态了,那肯定......
  • AtCoder ABC056D 题解
    题目直达0x00思路从大到小枚举每个元素,同时加入\(sum\)进行累计,当\(k\lesum\)时,便会返现之前的元素可以构成“好的组”(因为他们都大于\(p_i\)),即有用的,所以要清空。0x01举个例子36143我们对输入排序后,会得到\(p\)为。431这时,我们的\(i=1\),即\(p_i=......
  • AtCoder ABC228D 题解
    [ABC299D]FindbyQuery题解0x00题目分析题目传送门经过分析,我们得到的几个关键信息:\(n\le2\times10^5\)最多可以问法官\(20\)个问题。s[1]=0,s[n]=1分析\(n\)的范围,发现\(\log_n=17.6096\),刚好比\(20\)小一点点。这时便考虑二分的做法。看到s[1]=0,......
  • AtCoder ABC047D 题解
    题意理解&分析:大概的题意应该是十分清晰的,就是一个人要从\(1\)到\(n\)的城市中买苹果。另一个人要其中调整价格。这里的调整也不需要太多,就\(1\)就可以了。但是,如果有多组购买方案可以得到相同的利润,就还需要将其他相同的价格一并调整。这道题的关键就在于求出有几组购买......
  • CF1732D1 题解
    CF1732D1Balance题解题目解释输入一个\(op\)和\(x\),\(op\)有\(2\)种情况。\(op\)为+,则将\(x\)加入到集合中。\(op\)为?,则找到一个最小的\(k\),使\(k\timesx\)不在合集中。题目非常简单明了。具体实现这时,看到这句话:\(1\lex\le10^{18}\),所以不可......
  • 题解 CF1830C【Hyperregular Bracket Strings】
    卡特兰数一个长为\(2n\)的序列,填入括号,有多少种合法方案?\(C_n=\sum_iC_iC_{n-i-1}\),其中\(C_0=C_1=1\)。它的封闭形式是\(C_n=\binom{2n}{n}-\binom{2n}{n-1}\)。problem给定一个长度\(n\)和\(k\)个子区间\(\{[l1​,r1​],[l2​,r2​],…,[lk​,rk​]\}\)。问有多......
  • 【题解】CF754D Fedor and coupons(优先队列)
    【题解】CF754DFedorandcoupons题目链接CF754DFedorandcouponsCF1029CMaximalIntersection后者是前者的加强版。思路分析最开始,先考虑不删区间\((k=0)\)的情况:也就是给你一大堆区间,让你找他们的交集。这个还是比较好想的,我们刚开始让第二个区间与第一个区间相交......
  • AtCoder Beginner Contest 221 G Jumping sequence
    洛谷传送门AtCoder传送门这个数据范围让我们不得不往背包想。但是两维相互限制。考虑坐标系旋转\(45°\),转化为两维不相互限制。那我们现在相当于要安排正负号,使得\(\sum\limits_{i=1}^n\pmd_i\)等于一个给定的值\(K\)。考虑两边加上\(\sum\limits_{i=1}^nd_i\)......