http://acm.ustc.edu.cn/ustcoj/problem.php?id=1247
由于这是正整数序列,故其sum的数组是单调增的,有序的东西一般时间复杂度就是nlogn。
对每一位i,二分找出前面和后面最远的满足题目要求的那一位,然后取这两个距离差的min。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
#define N 100005
int a[N],b[N],n,s;
int search1(int w)
{
int x=0,y=w;
if (a[w]>s) return 1000000;
if (b[w]<=s) return 0;
int mid;
while (x<y)
{
mid=(x+y)/2;
if (b[w]-b[mid]<=s && b[w]-b[mid-1]>s) return mid;
else if (b[w]-b[mid]>s) x=mid+1;
else y=mid-1;
}
if (b[w]-b[mid]<=s && b[w]-b[mid-1]>s) return mid;
if (b[w]-b[mid+1]<=s && b[w]-b[mid]>s) return mid+1;
if (b[w]-b[mid-1]<=s && b[w]-b[mid-2]>s) return mid-1;
return mid;
}
int search2(int w)
{
int x=w,y=n;
if (b[w+1]-b[w]>s) return -1;
if (s>=b[n]) return n;
int mid;
while (x<y)
{
mid=(x+y)/2;
if (b[mid]-b[w]<=s && b[mid+1]-b[w]>s) return mid;
else if (b[mid]-b[w]>s) y=mid-1;
else x=mid+1;
}
if (b[mid]-b[w]<=s && b[mid+1]-b[w]>s) return mid;
if (b[mid-1]-b[w]<=s && b[mid]-b[w]>s) return mid-1;
if (b[mid+1]-b[w]<=s && b[mid+2]-b[w]>s) return mid+1;
return mid;
}
int main()
{
//freopen("a","r",stdin);
b[0]=0;
while (scanf("%d%d",&n,&s)!=EOF)
{
int i;
for (i=1;i<=n;i++) scanf("%d",&a[i]);
b[1]=a[1];
for (i=2;i<=n;i++) b[i]=b[i-1]+a[i];
b[n+1]=2000000005;
int max=-1;
for (i=1;i<=n;i++)
{
int t1,t2;
t1=i-search1(i);
t2=search2(i)-i;
int t;
if (t1<t2) t=t1;
else t=t2;
if (t>max && t!=0) max=t;
}
printf("%d\n",max);
}
return 0;
}