Bound Found POJ - 2566(尺取法)

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)/~

发布了652 篇原创文章 · 获赞 101 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/starlet_kiss/article/details/105433658