Description
you are given a 01 sequence whose size is n. you can change at most k 0 into 1 in the sequence.
now I want to know how many consecutive 1 in the sequce at most after you do the change.
Input
The first of input is an integer t which stands for the number of test cases.
for each test case, the first line contains two number n, k ( 1 <= n <= 100000, 0 <= k <= n ).
the next contains n element of the sequence, whose value is 0 or 1.
Output
output the answer in one line for each test case.
Sample Input
2
4 2
1 0 0 1
4 1
1 0 1 0
Sample Output
4
3
Source
baihacker&onmylove@scuacm
Sichuan University Programming Contest 2012 Preliminary
//分析:其中i-j中0的个数可以表达如下:j-i+1-(sum[j]-sum[i-1]);其中sum[i]表示前i个数之和。
分析表达式知假如i是确定的,那么j-i+1和sum[j]-sum[i-1]都是随着j而递增的,所以我们可以从i=1...n,每次遍历i为起点,要找到一个最大的j使得它和i之间的0的个数不大于k,由于之前的表达式是递增的所以可以每次二分出一个j,最后取最优,时间复杂度为O(n*logn);
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100005
struct NODE
{
int ti,num;
}node[maxn];
int a[maxn];
int main()
{
int t,n,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
int i,j;
memset(node,0,sizeof(node));
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
node[i].ti=i;
node[i].num+=node[i-1].num+a[i];
}
int tmp=0,best=0,flag=0;
for(i=1;i<=n;i++)
{
int lif=i,rig=n,mid=(lif+rig)>>1;
flag=0;
while(lif<=rig)
{
if((node[mid].ti-node[i].ti+1-(node[mid].num-node[i-1].num)>k))
rig=mid-1;
else
lif=mid+1;
mid=(lif+rig)>>1;
}
if(mid-i+1>best)
best=mid-i+1;
}
printf("%d\n",best);
}
return 0;
}