传送门:Problem 3061

https://www.cnblogs.com/violet-acmer/p/9793209.html

马上就要去上课了,先献上二分AC代码,其余的有空再补

题意:

  给定长度为 n 的整数数列 a[0,1,2,........,n]以及整数 S。

  求出总和不小于 S 的连续子序列的长度的最小值。

  如果解不存在,则输出 0。

题解:

  1、二分

    由于所有的元素都大于 0 ,所以数组a[ ] 的前缀和sum[ ]为递增的序列,满足二分的条件。

    首先确定子序列的起点为start(start的可能取值为 1,2,......,n)。

    假设区间[start,end]是以start为子序列起点的最小区间,则需要满足 sum[end]-sum[start-1] >= S,而确定满足条件的最小的 end 用二分即可在O(longn)的时间完成。

    所以总的时间复杂度为 O(nlogn)

  2、尺取法

    相关说明:

      设以a[start]为子序列起点的总和最初大于S的连续子序列为a[start,......,end],此时 res = end-start+1;

    (1):end++,找到最大的 k ,使得在去除当前子序列的前 k 个数后依旧满足 sum[end]-sum[start-1 + k] >= S,并判断是否需要更新 res。

    (2):重复(2)过程,直到 end > n 为止。

AC代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mem(a,b) (memset(a,b,sizeof(a)))
const int maxn=1e5+; int N,S;
int a[maxn];
int sum[maxn];
int binarySearch(int val)
{
int l=,r=N+;
while(r-l > )
{
int mid=l+((r-l)>>);
if(sum[mid] >= val)
r=mid;
else
l=mid;
}
return r;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mem(sum,);
scanf("%d%d",&N,&S);
int res=;
for(int i=;i <= N;++i)
{
scanf("%d",a+i);
sum[i] += sum[i-]+a[i];
}
for(int s=;s <= N;++s)
{
int t=binarySearch(sum[s-]+S);
if(t != N+)
res=(res== || (t-s+)<res ? t-s+:res);
}
printf("%d\n",res);
}
}

二分

 #include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define pb push
const int maxn=1e5+; int N,S;
int a[maxn];
queue<int >myqueue; int main()
{
int T;
scanf("%d",&T);
while(T--)
{
while(!myqueue.empty())
myqueue.pop();
scanf("%d%d",&N,&S);
for(int i=;i <= N;++i)
scanf("%d",a+i);
int end=;
int sum=;
int res=;
while(sum < S && end <= N)//先找到以1为序列起点的满足条件的最小的end
{
sum += a[end];
res++;
myqueue.pb(a[end++]);
}
if(sum >= S)
{
while(sum-myqueue.front() >= S)//找到满足条件的当前最小的范围
{
sum -= myqueue.front();
myqueue.pop();
res--;
}
while(end <= N)
{
myqueue.pb(a[end]);
sum += a[end++];
while(sum-myqueue.front() >= S)//步骤(2)
{
sum -= myqueue.front();
myqueue.pop();
}
res= res > myqueue.size() ? myqueue.size():res;//判断是否更新 res
}
}
else
res=;
printf("%d\n",res);
}
}
 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+; int N,S;
int a[maxn]; int Solve()
{
int start=,end=;
int res=;
int sum=;
while()
{
while(end <= N && sum < S)
sum += a[end++];
if(sum < S)
break;
res=(res == || (end-start) < res ? end-start:res);
sum -= a[start++];
}
return res;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&S);
for(int i=;i <= N;++i)
scanf("%d",a+i);
printf("%d\n",Solve());
}
}

尺取法&挑战程序设计竞赛

poj 3061(二分 or 尺取法)的更多相关文章

  1. POJ 3061 Subsequence ( 尺取法)

    题目链接 Description A sequence of N positive integers (10 < N < 100 000), each of them less than ...

  2. POJ 3061 Subsequence(尺取法)

    题目链接: 传送门 Subsequence Time Limit: 1000MS     Memory Limit: 65536K 题目描述 给定长度为n的数列整数以及整数S.求出总和不小于S的连续子 ...

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

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

  4. POJ 3061 (二分+前缀和or尺取法)

    题目链接: http://poj.org/problem?id=3061 题目大意:找到最短的序列长度,使得序列元素和大于S. 解题思路: 两种思路. 一种是二分+前缀和.复杂度O(nlogn).有点 ...

  5. POJ 3061 Subsequence 二分或者尺取法

    http://poj.org/problem?id=3061 题目大意: 给定长度为n的整列整数a[0],a[1],--a[n-1],以及整数S,求出总和不小于S的连续子序列的长度的最小值. 思路: ...

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

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

  7. 离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers

    题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问.还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前 ...

  8. poj 2566"Bound Found"(尺取法)

    传送门 参考资料: [1]:http://www.voidcn.com/article/p-huucvank-dv.html 题意: 题意就是找一个连续的子区间,使它的和的绝对值最接近target. ...

  9. POJ 2566 Bound Found(尺取法,前缀和)

    Bound Found Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5207   Accepted: 1667   Spe ...

随机推荐

  1. spring cloud bus原理总结

    1.spring cloud bus spring cloud是按照spring的配置对一系列微服务框架的集成,spring cloud bus是其中一个微服务框架,用于实现微服务之间的通信. spr ...

  2. EL表达式和JSTL标签库

    expresion language表达式语言 可以输出表达式的值.跟jsp的表达式脚本一样.计算表达式的值后输出.  EL表达式出现的目的是为了使JSP写起来更加简单,让jsp的代码更佳简化. 1. ...

  3. servlet请求转发

    来源:http://www.2cto.com/kf/201610/554591.html 请求转发:Servlet(源组件)先对客户请求做一些预处理操作(数据处理),然后把请求转发给其他Web组件(目 ...

  4. TCP报文格式详解

    TCP报文是TCP层传输的数据单元,也叫报文段. 1.端口号:用来标识同一台计算机的不同的应用进程. 1)源端口:源端口和IP地址的作用是标识报文的返回地址. 2)目的端口:端口指明接收方计算机上的应 ...

  5. SMBv1 is not installed by default in Windows 10 Fall Creators Update 2017 and Windows Server, Semi-annual Channel

    windows 10 rs3 release enable SMBv1 windows 10 rs3 release file sharing https://support.microsoft.co ...

  6. [读书笔记]Linux命令行与shell编程读书笔记03 文件系统等

    1. 文件系统的种类 ext ext2 ext3 ext4 JFS XFS 其中ext3 开始支持journal日志模式 与raid卡类似 有 数据模式  排序模式 以及回写模式 数据模式最安全 回写 ...

  7. spring学习总结(一)_Ioc基础(中)

    本篇文章继续上篇文章讲解Ioc基础,这篇文章主要介绍使用spring注解配置Ioc 上篇文章主要是通过xml配置文件进行Ioc的配置.这次进行改造下,通过注解进行配置 首先先看一个简单的demo 简单 ...

  8. JavaScript 教程 之基础教程

    1.js 错误 var objClass = { foo:1, bar:2 }; function printf() { var aaa:objClass; aaa.foo = 2; console. ...

  9. 使用libcurl 发送post请求

    SendHttpPost(string& strUrl, string& strPost, string& strResponse, int nTimeOut) { CURLc ...

  10. POJ2635-The Embarrassed Cryptographer-大整数素因子

    计算一个大整数(10^100)中有没有一个小于L的素因子.这个大整数是两个素数的乘积.其实就是RSA加密. 做法是把大整数表示成千进位,用数组存储,然后一位一位地取模. /*------------- ...