• 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
    ");
    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
    ");                                                                       
    65         else{
    66             printf("%d
    ",ans);
    67         }
    68     }
    69 
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    UIAlertView
    网络请求ASIhttp
    省份城市选择
    Certificates
    UTF8
    xcode增加注释插件
    常用片段 button Label
    开发铺助工具
    iOS UI框架
    iOS 引导页
  • 原文地址:https://www.cnblogs.com/greenaway07/p/11193936.html
Copyright © 2020-2023  润新知