POJ 3061 Subsequence 二分或者尺取法

题目大意:

给定长度为n的整列整数a[0],a[1],……a[n-1],以及整数S,求出总和不小于S的连续子序列的长度的最小值。

思路:

方法一:

首先求出各项的和sum[i],这样可以在O(1)的时间内算出区间上的总和,这样,枚举每一个起点i,然后二分搜索出结果大于sum[i]+tot的最小下标。(tot是题目中的S)

总的时间为O(nlogn)

方法二:

设以a[s]开始的总和最初大于S时的连续子序列为a[s]+a[s+1]+……a[t-1],这时,a[s+1]+a[s+1]+……a[t-2]<a[s]+a[s+1]+……a[t-2]<S,所以如果从a[s+1]开始总和最初超过S的连续子序列是a[s+1]+……a[t‘-1],则t<=t'。

故可以设计如下算法:

1.初始s=t=sum=0

2.只要依然有sum<S,就不断将sum加上a[t],并且t=t+1;

3.如果2中无法满足sum>=s则终止,否则ans=min(ans,t-s);

4.将sum减去a[s],s+=1后回到2

总复杂度为O(N)


1.二分法

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<algorithm>  
  4. using namespace std;  
  5. const int MAXN=100000+10;  
  6. const int INF=0x7fffffff;  
  7. int a[MAXN],sum[MAXN];  
  8. int search(int L,int R,int target) //(L,R]  
  9. {  
  10.     while(L<R-1)  
  11.     {  
  12.         int m=(L+R)>>1;  
  13.         if(sum[m]<target)  
  14.             L=m;  
  15.         else  
  16.             R=m;  
  17.     }  
  18.     return R;  
  19. }  
  20. int main()  
  21. {  
  22.     int T;  
  23.     scanf("%d",&T);  
  24.     while(T--)  
  25.     {  
  26.         int n,tot;  
  27.         scanf("%d%d",&n,&tot);  
  28.         sum[0]=0;  
  29.         for(int i=1;i<=n;i++)  
  30.         {  
  31.             scanf("%d",&a[i]);  
  32.             sum[i]=sum[i-1]+a[i];  
  33.         }     
  34.         int ans=INF;  
  35.         for(int i=1;i<=n&&sum[i]+tot<=sum[n];i++)  
  36.         {  
  37.             int t=search(i,n,tot+sum[i]);//sum[t]-sum[i]>=tot -> sum[t]>=tot+sum[i]  
  38.             ans=min(ans,t-i);  
  39.         }  
  40.         if(ans==INF)  
  41.             printf("0\n");  
  42.         else  
  43.             printf("%d\n",ans);  
  44.     }  
  45.     return 0;  
  46. }  

2.尺取法

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<algorithm>  
  3. using namespace std;  
  4. const int MAXN=100000+10;  
  5. const int INF=0x7fffffff;  
  6. int a[MAXN];  
  7.   
  8. int main()  
  9. {  
  10.     int T;  
  11.     scanf("%d",&T);  
  12.     while(T--)  
  13.     {  
  14.         int n,tot;  
  15.         scanf("%d%d",&n,&tot);  
  16.         for(int i=0;i<n;i++)  
  17.             scanf("%d",&a[i]);  
  18.         int s=0,t=0,sum=0,ans=INF;  
  19.         while(true)  
  20.         {  
  21.             while(sum<tot && t<n)  
  22.             {  
  23.                 sum+=a[t++];  
  24.             }  
  25.             if(sum<tot) break;  
  26.             ans=min(ans,t-s);  
  27.             sum-=a[s++];  
  28.         }  
  29.         if(ans==INF)  
  30.             printf("0\n");  
  31.         else  
  32.             printf("%d\n",ans);  
  33.     }  
  34.     return 0;  
  35. }  


http://www.huihui.cn/share/21766322
http://www.huihui.cn/share/21771540
http://www.huihui.cn/share/21768318
http://www.huihui.cn/share/21774676
http://www.huihui.cn/share/21776386
http://www.huihui.cn/share/21777526
http://www.huihui.cn/share/21778602
http://www.huihui.cn/share/21779780
http://www.huihui.cn/share/21769538
http://www.huihui.cn/share/21796362
http://www.huihui.cn/share/21797560
http://www.huihui.cn/share/21798428
http://www.huihui.cn/share/21799284
http://www.huihui.cn/share/21800568
http://www.huihui.cn/share/21801660
http://www.huihui.cn/share/21802512
http://www.huihui.cn/share/21803570
http://www.huihui.cn/share/21804704
http://www.huihui.cn/share/21805622
http://www.huihui.cn/share/21806554
http://www.huihui.cn/share/21807906
http://www.huihui.cn/share/21808750
http://www.huihui.cn/share/21809650
http://www.huihui.cn/share/21810574
http://www.huihui.cn/share/21811414
http://www.huihui.cn/share/21812130
http://www.huihui.cn/share/21813048
http://www.huihui.cn/share/20914604
http://www.huihui.cn/share/20923760
http://www.huihui.cn/share/20929736
http://www.huihui.cn/share/20934600
http://www.huihui.cn/share/20937504
http://www.huihui.cn/share/20941948
http://www.huihui.cn/share/20943998
http://www.huihui.cn/share/20945742
http://www.huihui.cn/share/20949462
http://www.huihui.cn/share/20951340
http://www.huihui.cn/share/20952726
http://www.huihui.cn/share/20955260
http://www.huihui.cn/share/20958518
http://www.huihui.cn/share/20960098
http://www.huihui.cn/share/20962202
http://www.huihui.cn/share/20963252
http://www.huihui.cn/share/20967618
http://www.huihui.cn/share/20999086
http://www.huihui.cn/share/21030922
http://www.huihui.cn/share/21038974
http://www.huihui.cn/share/21040184
http://www.huihui.cn/share/21041174
http://www.huihui.cn/share/21042072

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值