题解:P9046 [PA2021] Pandemia
mahaorui2012 · · 题解
思路
观察到初始有疫情的所有城市会把所有初始没有疫情的 城市分割为若干个区间。
怎么隔离
对于一个区间
l=1 或 r=n
则此时可以花费一天来将不为
1<l\le r<n
则此时又有两种情况:
r-l+1\le 2
此时只能将两个端点之一花费一天打疫苗,让另一个端点牺牲。
r-l+1>2
此时可以花费一天时间将其中一个端点打疫苗。
由于在给一个端点打完疫苗后区间全部被感染所需的时间会由
我们可以将这种操作称为一次“隔离”。
隔离什么
在不打疫苗的情况下,对于一个区间
l=1 或 r=n
当
1<l \le r<n
当
观察可发现,在
但是,这样做有一个小问题:
记得特判没有任何城市初始时被感染或全部城市初始时已被感染的情况。
AC CODE
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int n,m;
string s;
struct seg{
int l,r,t;
};vector<seg> e;
const bool cmp(const seg& a,const seg& b){
return a.t>b.t;
}
int main(){
int t;
cin>>t;
while(t--){
e=vector<seg>();
cin>>n;
cin>>s;
int cnt1=0;
for(int i=0;i<n;++i){
cnt1+=(s[i]=='1');
}if(!cnt1){
cout<<"0\n";
continue;
}else if(cnt1==n){
cout<<n<<'\n';
continue;
}
int curlen=0;
if(s[0]=='0') ++curlen;
for(int i=1;i<n;++i){
if(s[i]=='1'){
if(curlen){
e.push_back({i-curlen,i-1,(i==curlen?curlen*2:curlen)});
}curlen=0;
}else{
++curlen;
}
}if(curlen){
e.push_back({n-curlen,n-1,curlen*2});
}sort(e.begin(),e.end(),cmp);
m=e.size();
int curt=0;
int curin=0;
int ans=0;
while(curt*2<e[curin].t){
//cout<<e[curin].l<<' '<<e[curin].r<<' '<<e[curin].t<<endl;
if(e[curin].l==0 || e[curin].r==n-1){
ans+=e[curin].r-e[curin].l-curt+1;
++curt;
}else{
if(curt*2+2>=e[curin].t){
++ans;
++curt;
}else{
ans+=e[curin].r-e[curin].l-curt*2-1+1;
curt+=2;
}
}++curin;
if(curin>=m){
break;
}
}//cout<<e[curin].l<<' '<<e[curin].r<<' '<<e[curin].t<<endl;
cout<<n-ans<<'\n';
}return 0;
} C++