poj 2566 Bound Found

来源:互联网 发布:淘宝代购店铺推荐 编辑:程序博客网 时间:2024/04/29 05:22


Bound Found
Time Limit: 5000MS
Memory Limit: 65536KTotal Submissions: 2406
Accepted: 744
Special Judge

Description

Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronautic and Space Administration (that must be going through a defiant phase: "But I want to use feet, not meters!"). Each signal seems to come in two parts: a sequence of n integer values and a non-negative integer t. We'll not go into details, but researchers found out that a signal encodes two integer values. These can be found as the lower and upper bound of a subrange of the sequence whose absolute value of its sum is closest to t. 

You are given the sequence of n integers and the non-negative target t. You are to find a non-empty range of the sequence (i.e. a continuous subsequence) and output its lower index l and its upper index u. The absolute value of the sum of the values of the sequence from the l-th to the u-th element (inclusive) must be at least as close to t as the absolute value of the sum of any other non-empty range.

Input

The input file contains several test cases. Each test case starts with two numbers n and k. Input is terminated by n=k=0. Otherwise, 1<=n<=100000 and there follow n integers with absolute values <=10000 which constitute the sequence. Then follow k queries for this sequence. Each query is a target t with 0<=t<=1000000000.

Output

For each query output 3 numbers on a line: some closest absolute sum and the lower and upper indices of some range where this absolute sum is achieved. Possible indices start with 1 and go up to n.

Sample Input

5 1-10 -5 0 5 10310 2-9 8 -7 6 -5 4 -3 2 -1 05 1115 2-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -115 1000 0

Sample Output

5 4 45 2 89 1 115 1 1515 1 15



大致题意:解释一下输入输出好了,就是输入两个数,第一个数n指的是下一行要输的数的个数,第二个数k指的是target的个数。第二行输入n个数,第三行输入k个数t(target),要使第二行中的数中某些连续的子序列之和最接近t。输出的是最接近的这个数,以及子序列开头和结尾的下标。

思路:前缀和排序加尺取法。作业上面就标了尺取法。。。还不知道什么是尺取法啊。。于是就去百度了下当时看的是这个例子:http://blog.chinaunix.net/uid-24922718-id-4848418.html

写写我我当前对尺取法的理解吧。。(毕竟能力不足可能有错见谅)就是:用一个数组来记录某些需要处理的值,两个“指针”(只是用来记录下标的。。不是真正意义上的指针),我用的是head和tail,当不满足条件的时候,head就向前移动,直到满足条件就停下来,让tail向前移动,直到不满足条件了,再让head向前移动。。同时tail不能超过head,至于能不能等于head,经验不足。。以后再想好了。。至少这题不行。然后就是感觉尺取法一般要有个使head向前移动并停下来的条件,就是head向前移的时候是越来越接近目标的,因此这题就要先对前缀和排序了(原来是想直接做的。。后来看了网上的提示看到别人说要用前缀和排序。。想了一会儿才发现如果直接做的话没有办法让head停下来,因为不知道前面是否有更接近t的方法,毕竟这题是有正有负的)
感觉要是求最小的区间可以用尺取法呢。。

参考过别人的代码:http://blog.csdn.net/wiking__acm/article/details/9910415

昨天看了提示,有了思路就开始写,写完一交就RE了==第一次以为是数组开太大,看了别人的发现都是开这么大。。太渣了不知道RE可能是数组越界。。只知道可能是分母为零。。恩。。RE的原因总结下:(百度上找的。。du.com/link?url=mWDrDy7X-t0nrMnAo-vTaRQwWjwrb5kEtfCIZhEpB__O1iDB4ZR5sFyZIBF97aeud6l5UPuu4mDagN946gUlUK)

runtime  error (运行时错误)就是程序运行到一半,程序就崩溃了。

比如说:

①除以零

②数组越界:int a[3]; a[10000000]=10;

③指针越界:int * p; p=(int *)malloc(5 * sizeof(int)); *(p+1000000)=10;

④使用已经释放的空间:int * p; p=(int *)malloc(5 * sizeof(int));free(p); *p=10;

⑤数组开得太大,超出了栈的范围,造成栈溢出:int a[100000000];


这题我原来应该是数组越界了。。。。因为我一开始没限制tail小于head,while里面只限制了head<=n,最后tail直接就超过head然后越界,后来还WA了一次。。具体原因见代码
#include <iostream>#include <cstdlib>#include <cstdio>#include <algorithm>using namespace std;struct node{    int num,sum;//sum用来记录前缀和,num用来记录原来的顺序}s[100005];bool cmp(node x,node y){    return x.sum<y.sum;//按照前缀和从小到大排序}int main(){    int x;    int n,k,i,t,head,tail,rhead,result,rtail,tmp,min1;    while(scanf("%d %d",&n,&k) != EOF)    {        if(n==0&&k==0)break;        s[0].sum=0;//多放一个数进去        s[0].num=0;        for(i=1;i<=n;i++)        {            scanf("%d",&x);            s[i].sum=s[i-1].sum+x;            s[i].num=i;        }        sort(s,s+n+1,cmp);//这个地方错了两次,第一次粗心写成了(s+2,s+n+1,cmp),                          //  第二次改成(s+1,s+n+1,cmp)WA了。。                          //还是没有理解。。就算是第一个数也应该放进去排序的!        for(i=1;i<=k;i++)        {            scanf("%d",&t);            tail=0;            head=1;            min1=1000000001;            while(head<=n)            {                tmp=abs(s[head].sum-s[tail].sum)-t;                if(min1>abs(tmp))                {                    min1=abs(tmp);//整数的绝对值用的是abs,包含在cstdlib头文件里面,fabs的类型是double                    result=tmp+t;                    rhead=s[head].num;                    rtail=s[tail].num;                }                if(tmp<0)head++;                else if(tmp>0)tail++;                else break;//相等的话就说明达到目标了,就可以直接退出循环                if(tail==head)head++;//tail不能等于head,因为如果等于就相当于没有把任何数加起来,就是0            }            printf("%d %d %d\n",result,min(rhead,rtail)+1,max(rhead,rtail));        }    }    return 0;}








































0 0
原创粉丝点击