具体的解法请参看《浅谈数形结合思想在信息学竞赛中的应用》。本题中使用叉积可以避免所有浮点运算。
#include<cstdio>
#define maxn 100009
#define LL long long
using namespace std;
LL Cross(LL xa,LL ya,LL xb,LL yb)//向量(xa,xb)和向量(ya,yb)求叉积,通过叉积正负判断斜率关系
{
return xa*yb-ya*xb;
}
char s[maxn];
int q[maxn*2];
int sum[maxn];
int main()
{
int tt,n,l;
scanf("%d",&tt);
while(tt--)
{
scanf("%d%d%s",&n,&l,s+1);
for(int i=1;i<=n;i++)
if(s[i]=='1') sum[i]=sum[i-1]+1;
else sum[i]=sum[i-1];
int head=0,rear=-1;
int ansl=0,ansr=l;
for(int i=l;i<=n;i++)
{
while(rear-head>=1&&Cross(q[rear]-q[rear-1],sum[q[rear]]-sum[q[rear-1]],i-l-q[rear],sum[i-l]-sum[q[rear]])<=0)rear--;
q[++rear]=i-l;
while(rear-head>=1&&Cross(i-q[head],sum[i]-sum[q[head]],i-q[head+1],sum[i]-sum[q[head+1]])>=0)head++;
int it=q[head];
if(Cross(ansr-ansl,sum[ansr]-sum[ansl],i-it,sum[i]-sum[it])>0)
{
ansl=it,ansr=i;
}
else if(Cross(ansr-ansl,sum[ansr]-sum[ansl],i-it,sum[i]-sum[it])==0)
{
if(i-it<ansr-ansl)
{
ansr=i;
ansl=it;
}
}
}
printf("%d %d\n",ansl+1,ansr);
}
}