poj 3061 Subsequence

 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 }
View Code

 

posted @ 2019-07-16 11:46  鹤花之歌  阅读(133)  评论(0编辑  收藏  举报