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
题意:找出一段连续的序列,使得这个序列的和的绝对值和t的差值最小。输出这段区间的绝对值和区间的左右端点。
思路:尺取的前提条件就是序列必须是单调的,否则前进和后退根本找不出规律来,就没有办法尺取了。但是如果堆这个数组排序的话,就不能保证这是连续的了。我们先把这段序列的前缀和数组求出来,然后将前缀和出现的序列号一同保存下来,按照由小到大排序。这样序列就是单调的了。然后两个指针开始尺取,如果当前区间求出的和小于t的话,说明还可以变大一点,那么就r++;如果当前区间求出的和大于t的话,说明还可以变小一点,那么就l++。注意这是前缀和,l和r不能相同。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxx=1e5+100;
struct node{
int num;
int pos;
bool operator<(const node &a)const{
return num<a.num;
}
}p[maxx];
int a[maxx];
int n,m;
int main()
{
while(~scanf("%d%d",&n,&m)&&(n+m))
{
p[0].num=0;
p[0].pos=0;//这里需要解释一下,因为这是前缀和,不是原来的数组,添加一个0是因为有可能从头开始取元素,那样的话,p[l].num需要为0才可以。
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
p[i].num=p[i-1].num+a[i];
p[i].pos=i;
}
sort(p,p+1+n);//从0开始排序。
while(m--)
{
int t;
scanf("%d",&t);
int ans=inf,Ans;
int L=0,R=0;
int l=0,r=1;
while(r<=n)
{
int res=p[r].num-p[l].num;
if(abs(res-t)<ans)
{
ans=abs(res-t);
Ans=res;
L=p[l].pos;
R=p[r].pos;
}
if(res<t) r++;
else if(res>t) l++;
else break;
if(l==r) r++;
}
if(L>R) swap(L,R);
printf("%d %d %d\n",Ans,L+1,R);
}
}
return 0;
}
尺取就是需要多思考。
努力加油a啊,(o)/~