http://poj.org/problem?id=3061

题目大意:

给定长度为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.二分法

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100000+10;
const int INF=0x7fffffff;
int a[MAXN],sum[MAXN];
int search(int L,int R,int target) //(L,R]
{
while(L<R-1)
{
int m=(L+R)>>1;
if(sum[m]<target)
L=m;
else
R=m;
}
return R;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,tot;
scanf("%d%d",&n,&tot);
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
int ans=INF;
for(int i=1;i<=n&&sum[i]+tot<=sum[n];i++)
{
int t=search(i,n,tot+sum[i]);//sum[t]-sum[i]>=tot -> sum[t]>=tot+sum[i]
ans=min(ans,t-i);
}
if(ans==INF)
printf("0\n");
else
printf("%d\n",ans);
}
return 0;
}

2.尺取法

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=100000+10;
const int INF=0x7fffffff;
int a[MAXN]; int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,tot;
scanf("%d%d",&n,&tot);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int s=0,t=0,sum=0,ans=INF;
while(true)
{
while(sum<tot && t<n)
{
sum+=a[t++];
}
if(sum<tot) break;
ans=min(ans,t-s);
sum-=a[s++];
}
if(ans==INF)
printf("0\n");
else
printf("%d\n",ans);
}
return 0;
}

POJ 3061 Subsequence 二分或者尺取法的更多相关文章

  1. POJ 3061 Subsequence ( 二分 || 尺取法 )

    题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度.否则输出 0(序列的元素都是大于 0 小于10000) 分析 : 有关子序列和的问题,都可以考虑采用 ...

  2. poj 3061 Subsequence 二分 前缀和 双指针

    地址 http://poj.org/problem?id=3061 解法1 使用双指针 由于序列是连续正数 使用l r 表示选择的子序列的起始 每当和小于要求的时候 我们向右侧扩展 增大序列和 每当和 ...

  3. Poj 3061 Subsequence(二分+前缀和)

    Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12333 Accepted: 5178 Descript ...

  4. POJ 3061 Subsequence 二分查找

    题目大意:给出长度为n的一个序列,给出一个数字S,求长度最短的序列和大于等于S的连续子序列,输出该长度,如果没有答案输出0. 题目思路:看数据范围,这道题就是卡时间的.我们可以用sum[i]记录前i项 ...

  5. Atcoder Beginner Contest 155D(二分,尺取法,细节模拟)

    二分,尺取法,细节模拟,尤其是要注意a[i]被计算到和a[i]成对的a[j]里时 #define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> ...

  6. 题解报告:poj 3061 Subsequence(前缀+二分or尺取法)

    Description A sequence of N positive integers (10 < N < 100 000), each of them less than or eq ...

  7. POJ 3061 Subsequence【二分答案】||【尺取法】

    <题目链接> 题目大意: 给你一段长度为n的整数序列,并且给出一个整数S,问你这段序列中区间之和大于等于S的最短区间长度是多少. 解题分析:本题可以用二分答案做,先求出前缀和,然后枚举区间 ...

  8. poj 3061(二分 or 尺取法)

    传送门:Problem 3061 https://www.cnblogs.com/violet-acmer/p/9793209.html 马上就要去上课了,先献上二分AC代码,其余的有空再补 题意: ...

  9. POJ 3061 Subsequence 尺取法 POJ 3320 Jessica's Reading Problem map+set+尺取法

    Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13955   Accepted: 5896 Desc ...

随机推荐

  1. 【Codeforces Round #424 (Div. 2) A】Unimodal Array

    [Link]:http://codeforces.com/contest/831/problem/A [Description] 让你判断一个数列是不是这样一个数列: 一开始是严格上升 然后开始全都是 ...

  2. Android 第三方分享中遇到的问题以及解决方案

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 第三方登录和分享过程中难免遇到各种纠结的问题,下面将我遇到的分享给大家. 先说第三方登录 1.首先要 ...

  3. Windows操作系统下将Redis安装为服务

    安装服务: E:/Redis/Redis-x64-3.2.100/redis-server.exe --service-install E:/Redis/Redis-x64-3.2.100/redis ...

  4. 洛谷—— P2580 于是他错误的点名开始了

    https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次 ...

  5. 【安卓】数据库基于脚本的&quot;增量更新&quot;,每次更新时不需改动java代码、!

    思路: 1.当然是基于SQLiteOpenHelper.onCreate(第一次安装程序时调用).onUpdate(升级程序时调用) 2.用"脚本"(脚本制作详细方法问度娘)做数据 ...

  6. 阿里云server改动MySQL初始password---Linux学习笔记

    主要方法就是改动 MySQL依照文件以下的my.cnf文件 首先是找到my.cnf文件. # find / -name "my.cnf" # cd /etc 接下来最好是先备份my ...

  7. Boolean operations between triangle meshes

    Boolean operations between triangle meshes eryar@163.com Abstract. Boolean operations is one of basi ...

  8. JS错误记录 - 右侧悬浮框 - 缓冲运动

    本次练习错误总结: 1.  正确: startMove( document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop); ...

  9. js常用代码示例及解决跨域的几种方法

    1.阻止默认行为 // 原生js document.getElementById('btn').addEventListener('click', function (event) { event = ...

  10. scrollwidth ,clientwidth ,offsetwidth 三者的区别

    clientwidth:内容可视区域的宽度 offsetwidth:元素整体宽度 scrollwidth:实际内容的宽度