1 #include <iostream>
2 #include <algorithm>
3 #include <cmath>
4 #include <stdio.h>
5 #include <cstring>
6 #include <string>
7 #include <cstdlib>
8 #include <queue>
9 #include <stack>
10 #include <set>
11 #include <vector>
12 #include <map>
13 #include <list>
14 #include <iomanip>
15 #include <fstream>
16 using namespace std;
17 typedef long long ll;
18 const int maxn=1000009;
19 ll a[maxn];
20 int main()
21 {
22 //初始化前缀和数组a[maxn]
23 memset(a,0,sizeof(a));
24 int cas;
25 scanf("%d",&cas); //读入测试样例组数
26 ll n,sum,ans,s,pos,l;
27 while(cas--)
28 {
29 ans=100005; sum=0;
30 scanf("%I64d%I64d",&n,&s);
31 for(int i=1;i<=n;++i)
32 {
33 scanf("%I64d",&a[i]);
34 sum+=a[i];
35 a[i]+=a[i-1];//一边读一边计算前缀和
36 }
37 if(sum<s){//如果所有的数相加都没有要求的数字高 那么直接跳过这个样例
38 printf("0\n");
39 continue;
40 }
41
42
43 for(int i=1;i<=n;++i)
44 {
45 l=i-1;sum=0;pos=1;//倍增的思想,每次向右移动 pow(pos,2)的样子
46 while(pos)//当它移动到步长为0时
47 {
48 while(l+pos>n) pos>>=1;//因为是倍增,所以要担心它是否越界超出数组的实际长度,之前用if,还不够!!因为它减半一次以后仍然有可能超出范围必须用while
49 if(sum+a[l+pos]-a[l]<s)//之前的和sum加上之后区间的和如果仍然小于要求的数
50 {
51 sum+=a[l+pos]-a[l];//继续加上这段区间的和
52 l+=pos;//位置倍增,原来的右区间现在变成左区间
53 pos<<=1;//步长左移,相当于乘2
54 }
55 else{//发现sum加上之后区间的和大于等于要求的数,符合题目要求
56 ans=min(ans,l+pos-i+1);//那么答案就是原来答案与这整段区间的长度的较小值
57 pos>>=1;//因为步长太大了,所以pos步长需要右移一位,相当于除以2
58 }
59 }
60 //我一开始还在想,它假如pos除以2,回到上一步,上一步pos又乘2,不是在两者之间反复横跳吗...然后用草稿一步一步算以后发现
61 //它只是左端点不动,右边慢慢压缩pos
62 }
63 if(ans>100000)//发现答案长度超过数组实际长度,这不科学
64 printf("0\n");
65 else{
66 printf("%d\n",ans);
67 }
68 }
69
70 return 0;
71 }