删除最少的数字,反向思考是什么?答案很简单就是让一个序列中的子序列满足最大这个属性。
我们很容易想到的是,求出一个值为s的子序列,由总长度减去这个子序列的长度就是我们最少删除掉的值。
对于这种0,1计数达到某种条件的问题,我们还很容易想到通过某一个数组记录值为1的位置,这样的话我们就可以很容易得到两个1之间有着几个0。
接下来,通过这样的方式我们更加容易地想到可以通过序列长度来判断这个序列是否有着值为s这么多。
而对0的增加删除我们也可以通过这样的方式。
引申而出思考,我们记录了每一个具有某种关键性质点的相对位置,如果问题与这些相对距离有关,我们就可以通过这种方式来解决。
在记录相对坐标后,就可以通过这些相对坐标之间的距离,算出0的数量,1的数量,进而得到更大的区间长度。
#include<bits/stdc++.h>
using namespace std;
const int N=200050;
int a[N];
int b[N];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,s;
cin>>n>>s;
int cnt=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i])b[++cnt]=i;
}
if(cnt<s)
{
cout<<"-1"<<"\n";
continue;
}
b[0]=0;
b[cnt+1]=n+1;
int ans=0;
for(int l=1,r=s;r<=cnt;l++,r++)
{
int sum=b[r]-b[l]+1;
sum+=(b[l]-b[l-1]-1);
sum+=(b[r+1]-b[r]-1);
ans=max(ans,sum);
}
cout<<n-ans<<"\n";
}
return 0;
}
最后,让我们来思考下,相对区间大小问题。
int sum=b[r]-b[l]+1
为什么加一?
b数组中存储着每一个1的坐标,通过两个坐标相减,比如5和3,5-3=2,而正确答案是3,所以我们需要加一。