poj 2566"Bound Found"(尺取法)
参考资料:
[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"(尺取法)的更多相关文章
- POJ 2566 Bound Found(尺取法,前缀和)
Bound Found Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5207 Accepted: 1667 Spe ...
- poj 2566 Bound Found 尺取法 变形
Bound Found Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 2277 Accepted: 703 Spec ...
- poj 2566 Bound Found 尺取法
一.首先介绍一下什么叫尺取 过程大致分为四步: 1.初始化左右端点,即先找到一个满足条件的序列. 2.在满足条件的基础上不断扩大右端点. 3.如果第二步无法满足条件则到第四步,否则更新结果. 4.扩大 ...
- POJ 2566 Bound Found 尺取 难度:1
Bound Found Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 1651 Accepted: 544 Spec ...
- poj 2566 Bound Found(尺取法 好题)
Description Signals of most probably extra-terrestrial origin have been received and digitalized by ...
- poj 3061(二分 or 尺取法)
传送门:Problem 3061 https://www.cnblogs.com/violet-acmer/p/9793209.html 马上就要去上课了,先献上二分AC代码,其余的有空再补 题意: ...
- POJ 3061 Subsequence ( 尺取法)
题目链接 Description A sequence of N positive integers (10 < N < 100 000), each of them less than ...
- poj 3320 复习一下尺取法
尺取法(two point)的思想不难,简单来说就是以下三步: 1.对r point在满足题意的情况下不断向右延伸 2.对l point前移一步 3. 回到1 two point 对连续区间的问题求 ...
- POJ 3061 Subsequence ( 二分 || 尺取法 )
题意 : 找出给定序列长度最小的子序列,子序列的和要求满足大于或者等于 S,如果存在则输出最小长度.否则输出 0(序列的元素都是大于 0 小于10000) 分析 : 有关子序列和的问题,都可以考虑采用 ...
随机推荐
- python设计模式第十九天【职责链模式】
1.应用场景 (1)将一个任务拆分为具有顺序的多个部分,每个类完成相应的部分,并且顺序执行 (2)软件窗口的消息传播 (3)SERVLET容积的过滤器Filter的实现 2.代码实现 #!/usr/b ...
- 10.Service资源发现
Kubernetes Pods是不可控的.每当一个pod停止后,他不是重启,而是重建.ReplicaSets特别是Pods动态地创建和销毁(例如,当向外扩展或向内扩展时).虽然每个PodIP地址都有自 ...
- 【python练习题】程序2
2.题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%:20万到40 ...
- mosquitto发布消息
./mosquitto_pub -t '$SYS/broker/clients/status/online' -m 1
- python的图形模块PIL小记
前言: 跟我一块住的室友是个搞通信,每天下班后基本必须做的事情是,第一P图,将那些不合格的图片上的数据,p成合格的.第二就是将做好的P图以及产生的日志文件按照固定的名字重新命名.我为了他能够早点睡觉, ...
- springMVC整理02--常用注解的使用
1.使用@RequestMapping 映射请求 1.1在类和方法上添加@RequestMappingSpringMVC 使用@RequestMapping 为控制器指定可以处理哪些 URL 请求. ...
- BZOJ1012 最大数maxnumber
单调栈的妙处!! 刚看到这题差点写个splay..但是后来看到询问范围的只是后L个数,因为当有一个数新进来且大于之前的数时,那之前的数全都没有用了,满足这种性质的序列可用单调栈维护 栈维护下标(因为要 ...
- LSM
1.MySQL存储引擎: B+树 https://blog.csdn.net/qq_26222859/article/details/80631121 2.HBase LSM树 核心:将对数据的修改增 ...
- CCF WC2017 & THU WC2017 旅游记
day-x 真·旅游 去了杭州的一些景点,打了几场练习赛. day0 报到日 领资料.入住,中午在食堂吃饭,感觉做的挺好的,和二高食堂差不多.晚上还有开幕式. day1~day4 白天讲课,晚上营员交 ...
- bzoj 1452: [JSOI2009]Count (二维树状数组)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1452 思路: 对每个颜色开一个二维树状数组维护就好了 实现代码: #include<b ...