给你一个01串,找一个长度至少为L的连续子串,使平均值最大(1最多)。
这道题是数形结合,要结合着图看,推荐看紫书或是一些有图的代码,大致思想是把平均值和直线斜率对应起来然后清除上凸点。
AC代码:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
const int maxn=100010;
int a[maxn],q[maxn];
char s[maxn];
int solve(int x1,int x2,int x3,int x4)
{
return (a[x2]-a[x1])*(x4-x3)-(a[x4]-a[x3])*(x2-x1);
}
int main()
{
int n,t;
cin>>t;
while(t--)
{
int l;
scanf("%d%d%s",&n,&l,s+1);
a[0]=0;
for(int i=1;i<=n;i++)
a[i]=a[i-1]+s[i]-'0';
int tl=0,tr=l;
int i=0,j=0;
for(int t=1;t<=n;t++)
{
while(i<j-1&&solve(q[j-1],t-l,q[j-2],t-l)<0)
j--;
q[j++]=t-l;
while(i<j-1&&solve(q[i+1],t,q[i],t)>=0)
i++;
int tt=solve(q[i],t,tl,tr);
if(tt>0||tt==0&&(t-q[i]<tr-tl))
tr=t,tl=q[i];
}
cout<<tl+1<<' '<<tr<<endl;
}
return 0;
}