acwing 5438. 密接牛追踪2
农夫约翰有 NN 头奶牛排成一排,从左到右依次编号为 1∼N。
不幸的是,有一种传染病正在蔓延。
最开始时,只有一部分奶牛受到感染。
每经过一个晚上,受感染的牛就会将病毒传染给它左右两侧的牛(如果有的话)。
一旦奶牛被感染,它就会一直被感染,无法自愈。
给定一个经过若干个夜晚后的奶牛的整体状态,其中哪些奶牛已经被感染,哪些奶牛尚未被感染统统已知。
请你计算,最开始时就受到感染的奶牛的最小可能数量。
输入格式
第一行包含整数 N。
第二行包含一个长度为 N 的 01 序列,用来表示给定的奶牛的整体状态,其中第 i 个字符如果是 1 则表示第 i 头奶牛已经被感染,如果是 0则表示第 i 头奶牛尚未被感染。
输出格式
一个整数,表示最开始时就受到感染的奶牛的最小可能数量。
数据范围
1≤N≤3×10^5
输入样例1:
5
11111
输出样例1:
1
样例1解释
初始时,任意一头奶牛被感染,一定天数后都可以使得所有奶牛被感染。
输入样例2:
6
011101
输出样例2:
4
样例2解释
唯一一种可能是给定状态是没有经过任何夜晚时所有奶牛的状态,所以输入中被感染的 4 头奶牛都在最开始时就受到感染。
思路:暴力思路是模拟倒推感染,两端被感染的奶牛群可以先从内端递减,其余奶牛群从两边递减。这样最后当不能在减时,在考虑两端的最小奶牛情况。通过模拟的思路后,不难发现最后决定初始最小奶牛数的是(除两端外)当前被感染数最少的奶牛群,借此得出最大的感染天数。这里大致分为二种情况:
- 两端和中间都有被感染的奶的牛群。
- 两端有而中间没有被感染奶的牛群。
- 两端没有而中间有被感染奶的牛群。
第一种情况需要判断最大的感染天数是否大于两端奶牛群数量;第二种情况直接以最小的奶牛群数量-1为最大感染天数;第三种情况可套用一种。最后附上AC代码,太菜勿喷/(ㄒoㄒ)/~~
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+10;
int n,cnt;
int a[N];
int b[N];
string s;
int cmp(int a,int b){
return a<b;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
cin>>s;
int flag=0;
for(int i=0;i<s.size();i++)
{
a[i+1]=s[i]-'0';
if(s[i]=='1'){
if(!flag)cnt++,b[cnt]=1;
else b[cnt]++;
flag=1;
}else flag=0;
}
for(int i=1;i<=cnt;i++)
cout<<b[i]<<' ';
cout<<endl;
int ans=0,r=1,l=cnt,mod;
int da=0;
if(s[0]=='1')r=r+1;
if(s[s.size()-1]=='1')l=cnt-1;
if(r<=l){
sort(b+r,b+l+1,cmp);
if(b[r]%2)da=b[r]/2;else da=b[r]/2-1;
}
if(da){
mod=da;
if(r==2){
if(mod>=b[1])mod=b[1]-1;
}
if(l==cnt-1){
if(mod>=b[cnt])mod=b[cnt]-1;
}
mod=2*mod+1;
for(int i=1;i<=cnt;i++)
if(b[i]%mod)ans+=b[i]/mod+1;else ans+=b[i]/mod;
}else{
mod=min(b[1],b[cnt])-1;
mod=2*mod+1;
for(int i=1;i<=cnt;i++)
if(b[i]%mod)ans+=b[i]/mod+1;else ans+=b[i]/mod;
}
cout<<da<<endl;
cout<<mod<<endl;
cout<<ans;
return 0;
}