传送门

参考资料:

  [1]:http://www.voidcn.com/article/p-huucvank-dv.html

题意:

  题意就是找一个连续的子区间,使它的和的绝对值最接近target。

题解:

  这题的做法是先预处理出前缀和,然后对前缀和进行排序,再用尺取法贪心的去找最合适的区间。

  要注意的是尺取法时首尾指针一定不能相同,因为这时区间相减结果为0,但实际上区间为空,这是不存在的,可能会产生错误的结果。

  处理时,把(0,0)这个点也放进数组一起排序,比单独判断起点为1的区间更方便。

  还有ans初始化的值INF一定要大于t的最大值。

  最后说说这个题最重要的突破口,对前缀和排序。为什么这么做是对的呢?

  因为这题是取区间的和的绝对值,所以所以用sum[r]-sum[l] 和 sum[l]-sum[r]是没有区别的。

  这样排序后,把原来无序的前缀和变成有序的了,就便于枚举的处理,并且不影响最终结果。

  以上分析来自参考资料[1]。

AC代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define P pair<int ,int >
const int maxn=1e5+; int n,k;
P p[maxn]; bool cmp(P _a,P _b){
return _a.second < _b.second;
}
void Solve(int t)
{
int l=,r=;
int resL=p[l].first,resR=p[r].first;//先假设区间[1,p[1].first]为解
int resSum=p[r].second-p[l].second;
while(r <= n)
{
int curSum=p[r].second-p[l].second;
if(abs(curSum-t) < abs(resSum-t))//判断是否可以更新 resSum
{
resSum=curSum;
resL=p[l].first;
resR=p[r].first;
}
if(curSum < t)//如果当前区间值过小,增大当前值
r++;
else if(curSum > t)//如果当前区间值过大,减小当前值
l++;
else
break;
if(l == r)
r++;
}
if(resL > resR)
swap(resL,resR);
printf("%d %d %d\n",resSum,resL+,resR);//while()循环中做区间减法时始终左边界一直被减掉
}
int main()
{
// freopen("C:\\Users\\lenovo\\Desktop\\in.txt\\poj2566.txt","r",stdin);
while(~scanf("%d%d",&n,&k),n != || k != )
{
int sum=;
for(int i=;i <= n;++i)
{
int val;
scanf("%d",&val);
sum += val;
p[i]=P(i,sum);
}
p[]=P(,);
sort(p,p+n+,cmp);
while(k--)
{
int t;
scanf("%d",&t);
Solve(t);
}
}
return ;
}

我的理解:

  为什么对前缀和用尺取法是正确的呢?

  定义 pair<int ,int > 型变量 p[ maxn ];

  p[ i ].first : 右边界;

  p[ i ].second : 前 p[ i ].first 项和;

  将 p 按前缀和从小到大排序后,如图所示:

  

  纵坐标 : 排序后的前缀和

  假设 ( p[b].second-p[a].second ) 距 t 最近 , resSum = p[b].second-p[a].second;

  问题1:当 R 来到区间(a,b)时,L 有可能超过 a 吗?

  答案:不会。

  分析如下:当 a < R < b , L = a 时, 令 curSum=p[R].second-p[L].second;

  易得 curSum < resSum;

  根据 Solve() 中 while() 循环的代码,只由当 curSum > target 时,才会使 L++;

  假设 curSum > target , 则 resSum > curSum > target,那么答案就为 curSum 所标示的区间而不是resSum 所表示的区间,与假设不符;
  故当 L = a , a < R < b 时,curSum < target ,直到 R 来到 b 。

  问题2:当 L < a 时,R 有可能超过 b 吗?

  答案:不会。

  分析如下:当 L < a , R = b 时,令 curSum=p[R].second-p[L].second;

  易得 curSum > resSum;

  根据 Solve() 中 while() 循环的代码,只由当 curSum < target 时,才会使R++;

  假设 curSum < target , 则 resSum < curSum < target,那么答案就为 curSum 所标示的区间而不是resSum 所表示的区间,与假设不符;

  故当 R = b , L < a 时,curSum > target ,直到 L 来到 a 。

  综上所述,L,R一定会来到答案所对应的区间。

  问题3:为什么要加入 (0,0)点?

  根据Solve()中的while()循环可知,curSum求的是L,R区间的差集(大-小)的和,如果答案的左区间为 1 呢?

  不加入 (0,0) 点就永远也不可能使某两区间的差集(大-小)包含 1 .

  或者说可以另用一重循环判断,感觉加入 (0,0)点更美观,哈哈哈。

poj 2566"Bound Found"(尺取法)的更多相关文章

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

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

  2. poj 2566 Bound Found 尺取法 变形

    Bound Found Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 2277   Accepted: 703   Spec ...

  3. poj 2566 Bound Found 尺取法

    一.首先介绍一下什么叫尺取 过程大致分为四步: 1.初始化左右端点,即先找到一个满足条件的序列. 2.在满足条件的基础上不断扩大右端点. 3.如果第二步无法满足条件则到第四步,否则更新结果. 4.扩大 ...

  4. POJ 2566 Bound Found 尺取 难度:1

    Bound Found Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 1651   Accepted: 544   Spec ...

  5. poj 2566 Bound Found(尺取法 好题)

    Description Signals of most probably extra-terrestrial origin have been received and digitalized by ...

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

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

  7. POJ 3061 Subsequence ( 尺取法)

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

  8. poj 3320 复习一下尺取法

    尺取法(two point)的思想不难,简单来说就是以下三步: 1.对r point在满足题意的情况下不断向右延伸 2.对l point前移一步 3.  回到1 two point 对连续区间的问题求 ...

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

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

随机推荐

  1. 莫烦theano学习自修第十天【保存神经网络及加载神经网络】

    1. 为何保存神经网络 保存神经网络指的是保存神经网络的权重W及偏置b,权重W,和偏置b本身是一个列表,将这两个列表的值写到列表或者字典的数据结构中,使用pickle的数据结构将列表或者字典写入到文件 ...

  2. ERP系统的问题

    1.业务统计报表导出超时 2.库存统计相关接口查询容易导致慢查询,而且慢查询出现在主库上

  3. font_awesome的icon库的使用

    1.使用cdn引入font_awesome图标库的css文件 例如:index.htm <html><head><title>font_awesome test&l ...

  4. 解决mybatis generator警告Cannot obtain primary key information from the database, generated objects may be incomplete

    使用 mybatis generator 生成pojo.dao.mapper时 经常出现 Cannot obtain primary key information from the database ...

  5. 用dbexpress连接sqlserver数据库

    SQLConnection1.Params.clearSQLConnection1.Params.Values['ServerName'] := '192.168.0.112'; SQLConnect ...

  6. Eclipse:报错Failed to read artifact descriptor for org.springframework.boot:spring-boot-autoconfigure:jar:2.1.2.

    导入SVN下载的MAVEN项目时springboot报错: pom.xml文件报错 Failed to read artifact descriptor for org.springframework ...

  7. 解析$(this).data('type');

    html: <button type="button" class="layui-btn layui-btn-sm" data-type="ad ...

  8. hdu 5652(并查集)

    题意:很久之前,在中国和印度之间有通路,通路可以简化为一个n*m的字符串,0表示能通过,1表示障碍,每过一年就有一个坐标变成1,问你什么时候,通路彻底无法通过: 解题思路:无向图的连通性,一般直接搜索 ...

  9. Spring MVC 使用介绍(三)—— Controller接口控制器

    一.概述 Controller接口类图如下,其中,BaseCommandController已从Spring 4移除 基于继承Controller接口的方式已经不推荐使用,仅供学习参考 二.基于Con ...

  10. BZOJ3724PA2014Final Krolestwo——欧拉回路+构造

    题目描述 你有一个无向连通图,边的总数为偶数.设图中有k个奇点(度数为奇数的点),你需要把它们配成k/2个点对(显然k被2整除).对于每个点对(u,v),你需要用一条长度为偶数(假设每条边长度为1)的 ...