poj
来源:互联网 发布:stc单片机系统分析 编辑:程序博客网 时间:2024/06/16 12:11
Bound Found
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 4861 Accepted: 1558 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 10
3
10 2
-9 8 -7 6 -5 4 -3 2 -1 0
5 11
15 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
15 100
0 0
Sample Output
5 4 4
5 2 8
9 1 1
15 1 15
15 1 15
Source
Ulm Local 2001
题意: 给你n,k给你n个可正可负的数列,然后给你k次询问,让你求出在序列中一段连续的序列和的绝对值最接近询问值,然后输出最接近的数,以及区间范围
分析: 这个就有点意思了,一开始都是正数,直接尺取来进行查找就行,但是这个可正可负,就有点难搞了,不能用常规的思路了,因为要想用尺取的前提是一个有序的,可判定的序列,由于题目说的是连续序列和的绝对值,也就是说我们只需要知道两个端点即可,不用管谁前谁后,看了dalao 的解题发现了一种比较有思维的方法,就是利用前缀和来进行判定,我们来枚举前缀和的两个端点,从而可以找到一个最接近询问值的数,我们在存前缀和的同时还得把相应的坐标给存上,这里可以建个结构体,因为一会还要对前缀和进行排序,于是这里直接利用stl里面的pair来进行存储即可(因为pair自带比较,先对first升序,如果一样的话,再对second升序),然后我们设置一个compare来进行比较选出和询问值差别最小的,进行尺取即可
注意: (1) 要在pair第一个虚加一个(0,0),因为考虑后面可能是前几项的和,如果去掉的话取不到这个值;
(2) 自己可以模拟一下为什么最后在左端点加一(这个前缀和其实是包括这一位之前的和,减去的话其实是算的
参考代码
#include <cstdio>#include <algorithm>#include <iostream>#define fi first#define se secondusing namespace std;const int N = 1e5 + 10;pair<int,int> preSum[N];int main(){ ios_base::sync_with_stdio(0); int n,m; while(cin>>n>>m,n+m){ preSum[0] = make_pair(0,0); for(int i = 1;i <= n;i++){ cin>>preSum[i].fi; preSum[i].se = i; preSum[i].fi += preSum[i-1].fi; } sort(preSum,preSum+n+1); while(m--){ int x;cin>>x; int l = 0,r = 1,compare = 1<<30,ans,ansL,ansR; while(compare){ int t = preSum[r].fi - preSum[l].fi; if(abs(t-x) < compare){ ans = t; ansL = preSum[l].se; ansR = preSum[r].se; compare = abs(t - x); } if(t < x && r < n) r++; else if (l < n)l++; if(l == r && r < n) r++; if(r == n && l == n) break; //这里的break要控制好 } if(ansL > ansR) swap(ansL,ansR); ansL++; cout<<ans <<' '<<ansL<<' '<<ansR<<endl; } } return 0;}
- 如有错误或遗漏,请私聊下UP,thx