蓝桥杯每日一题——Acwing 5438. 密接牛追踪2
目录
思路:
代码:
思路:
可将本题转换为一个区间覆盖问题。
首先可以将r天感染后的所有1找出,即给出若干个全为1的线段。
假设最开始有一头牛感染,经过r天,这头牛会把左边的r头牛感染右边r头牛也感染,相当于每头初始被感染的牛都可以感染长度为2r+1的区间,将这些区间覆盖最开始的区间得到感染后的情况,即可转换为区间覆盖问题。
可知所有的1区间都是不相连的,即初始时所有的段与段之间都是独立的,则就可以分别考虑每一段,对每一段中,每一个初始被感染的牛都可以在此区间内进行区间覆盖
则问最开始时就受到感染的牛的最小可能数等价于:问最少用多少个长度为2r+1的区间可以将其覆盖,当然区间可以重复覆盖,因为一头牛被感染后可以重复感染
由下图公式可知,最少需要的区间数为(假设该区间长度为c)[c/(2r+1)](上取整)
由公式可知(其实想想也知道),天数越多开始被感染的牛越少x越大越好,但是能有多大?
这里为什么要限制天数呢?是因为给出的经过r个夜晚后的感染情况有0有1,如果不限制天数,结果一定都是1,不符合题目的要求
r的多少需要考虑每一段区间对r的限制
有两种情况:
情况1:当考虑该区间c两边都是0的时候,用来覆盖c区间的区间(2r+1)一定不能超过c,因为左右两边都是0,比如如果大于的话左右两边应该都被感染了,但是实际并没有。即有2r+1<=c,r<=[(c-1)/2]下取整
情况2:对于左右边界,当是最左边的牛感染时取得最多感染天数,为c-1,右边同理,即天数r<=c-1
还有一种极端情况即最终所有牛都被感染了,这个时候只需要1头牛,最多经过r-1 天
x需要满足上面每一个不等式需要取交集,即通过min实现
求下取整:除法
求上取整:(a+b-1)/b
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>using namespace std;const int N=300010;int n;
char s[N];
vector<int> cnt;//存每段区间的长度
//
int main()
{cin>>n;//牛的数量 for(int i=0;i<n;i++)//牛的感染情况 cin>>s[i]; int r=n;//取r(感染天数)的最大值 for(int i=0;i<n;i++){if(s[i]=='0') continue;//没有被感染//表示当前第一头被感染的牛,左边界int j=i+1;//用j来枚举右边界while(j<n&&s[j]=='1') j++;int c=j-i;//小区间长度int d=(c-1)/2;//天数,先假设是中间的情况//判断是否是左右两侧if(!i||j==n)//当i=0是左侧,当j==n右侧 d=c-1;r=min(r,d);//r需要满足所有不等式,即取交集cnt.push_back(c);//存入当前区间的长度i=j;//更新i }int res=0;//一共需要多少小区间 for(int c:cnt)res+= (c+2*r)/(2*r+1);cout<<res<<endl;return 0; }