1704C Virus
文章目录
题意
n个房子围成一圈,m个房子已被感染,每一个晚上,会发生如下事情:
- 被感染的房子会将它相邻的,未被感染的房子感染;
- 选择一个房子守护,它将被永久保护,不再被感染;
在数个夜晚进行如上操作,使得最后被感染的房子数量最少;
输出最少的被感染的房子的数量;
思路
正难则反:求最多能保护几个房子;
把被感染房子间的未感染房子列为数个区间,将这些区间按长度从小到大排序;
先保证大区间的房子们不被感染——选择邻近被感染房子的房子保护,最多耗费两个夜晚可以保护这个区间,被保护的房子数为:
b
[
i
]
−
(
2
∗
c
u
r
+
1
)
;
b[i] - ( 2 * cur + 1 );
b[i]−(2∗cur+1);
b[i]为这个区间最开始的干净房子数,cur为已进行的夜晚数;
遍历数个区间直到没有房子可以保护;
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6+10;
int n,m;
int a[N],b[N];
int cal(){
int res = 0;
for(int i = 0 ; i < m ; i++ ){
b[ i ] = a[i + 1] - a[ i ] - 1;//?
}
sort(b , b + m );
int cur = 0 ; //cur为当前夜晚数,现在是第0夜;
for(int i = m - 1 ; i >= 0 ; i-- ){
if(b[i] <= 2 * cur) break;
if(b[i] == 2 * cur + 1){
res+=1;
cur++;
}else {
res += b[i] - ( 2 * cur + 1 );
cur += 2;
}
}
return n - res ;
}
void solve(){
cin>>n>>m;//n个房子,m个被感染的房子;
for(int i = 0 ; i < m ; i++ ){
cin>>a[i];
}
sort(a , a + m);
a[m] = a[0] + n;
int res = cal();
cout<<res<<endl;
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
}