Bound Found
| Time Limit: 5000MS |
|
Memory Limit: 65536K |
| Total Submissions: 1338 |
|
Accepted: 443 |
|
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
Source
Ulm Local 2001好題。題意就是找一個連續的子區間,使它的和的絕對值最接近target。這題的做法是先預先處理出首碼和,然後對首碼和進行排序,再用尺取法貪心的去找最合適的區間,要注意的是尺取法時首尾指標一定不能相同,因為這時區間相減結果為0,但實際上區間為空白,這是不存在的,可能會產生錯誤的結果。處理時,把(0,0)這個點也放進數組一起排序,比單獨判斷起點為1的區間更方便。還有ans初始化的值INF一定要大於t的最大值。最後說說這個題最重要的突破口,對首碼和排序。為什麼這麼做是對的呢?以為這題是取區間的和的絕對值,所以所以用sum[r]-sum[l]
和 sum[l]-sum[r]是沒有區別的。這樣排序後,把原來無序的首碼和變成有序的了,就便於枚舉的處理,並且不影響最終結果。
#include<cstdio>#include<iostream>#include<algorithm>using namespace std;const int maxn = 100000 + 5;const int INF = 2000000000;typedef pair<int, int> P;typedef long long LL;P p[maxn];int Abs(int x){return x<0?-x:x;}int n;void query(int tar){ int s = 0,e = 1,Min = INF; int ansl,ansr,ansx; while(s <= n && e <= n){ int tem = p[e].first-p[s].first; if(Abs(tem-tar) < Min){ Min = Abs(tem-tar); ansx = tem; ansl = p[s].second; ansr = p[e].second; } if(tem > tar) s++; else if(tem < tar) e++; else break; if(s == e) e++; } if(ansl > ansr) swap(ansl,ansr); printf("%d %d %d\n",ansx,ansl+1,ansr);}int main(){ int m; while(scanf("%d%d",&n,&m)){ if(n == 0 && m == 0) break; p[0] = P(0,0); int sum = 0; for(int i = 1;i <= n;i++){ int tem; scanf("%d",&tem); sum += tem; p[i] = P(sum,i); } sort(p,p+n+1); while(m--){ int x; scanf("%d",&x); query(x); } } return 0;}