解题思路:
要有k个连续编号的灯,则枚举每个长度为k的区间,假设把这个区间的全都修好,求其最小修好的灯的数量。
区间固定,所以考虑枚举每个区间的情况,在输入的时候初始化,如果灯坏则light[i]为1,否则为0.
1.把每一个区间灯坏的情况做一个统计(前缀做统计),然后从k开始扫描这个数组,计算需要修好多少盏灯,取最小。
#include<bits/stdc++.h>
#define MAX 100010
using namespace std;
using gg = long long;
gg n,k,b;
gg light[MAX];//lightp[i]为1表示这个地方坏了。
gg sum[MAX];//前i个地方有多少坏的
gg res=1e9;
int main()
{
cin>>n>>k>>b;
int t;
for(int i=0;i<b;i++)
{
cin>>t;
light[t]=1;
}
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+light[i];//求取前缀和
}
for(int i=k;i<=n;i++)
{
res = min(res,sum[i]-sum[i-k]);//求每个区间需要修多少盏灯
}
cout<<res<<"\n";
return 0;
}
2.利用一个队列,每次扫描新的值,如果是坏的,则sum+=1,入队,如果队头(要出队那个)是坏的,则sum-=1,每次扫描取最小就好了。
#include<bits/stdc++.h>
#define MAX 100010
using namespace std;
using gg = long long;
gg n,k,b;
gg light[MAX];//lightp[i]为1表示这个地方坏了。
int res=1e9;
int main()
{
cin>>n>>k>>b;
int t;
for(int i=0;i<b;i++)
{
cin>>t;
light[t]=1;
}
int sum = 0;
int right = k;
for(int i=1;i<=right;i++)
{
if(light[i])
{
sum+=1;
}
}
res = sum;
int left = 1;
for(int right = k+1;right<=n;right++)
{
if(light[right]==1)
{
sum+=1;
}
if(light[left]==1)
{
sum-=1;
}
res = min(res,sum);
left+=1;
}
cout<<res<<"\n";
return 0;
}