#POJ 2566 Bound Found (尺取 前缀和)

Bound Found

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 8190 Accepted: 2661 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

题目大意 :输入一个长度为 N 的序列, 有M次访问, 每次访问输入一个数 K, 让你找到序列中 连续子序列的和的绝对值与所给的数的差值的最小值, 并输出某个正确的区间和该区间的和的绝对值

思路 : 尺取经典例题, 由于题目给的数据有负数,所以不可以直接尺取, 因为不满足单调性, 所以先记一下每个数的前缀和和对应的下标, 按照前缀和排序, 这样就满足单调性了(题目问的是区间绝对值的和, 如果没有这个条件, 那么就无法尺取),然后正常尺取并记录区间就好

Accepted code

#include<iostream>
#include<algorithm>
#include<functional>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 2e5 + 100;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }

struct node
{
	int id, x;
}p[MAXN];
bool cmp(node a, node b) {
	return a.x < b.x;
}
int c, n, m, k;
int ans, L, R, sum;
void init() {
	sum = 0, p[0] = { 0, 0 };
}
void Solve(int x) {
	int l = 0, r = 1, tmp = INF; ans = 0;
	L = 0, R = 1;
	while (r <= n && l <= n) {
		int tot = p[r].x - p[l].x;
		if (abs(tot - x) < tmp) {  // 差值小于当前最小值
			tmp = abs(tot - x);  //更新
			L = p[l].id;
			R = p[r].id; // 记录区间
			ans = tot;  // 记录区间和绝对值
		}
		if (tot > x) l++;
		else if (tot < x) r++;
		else break;
		if (l == r) r++; 
	}
	if (L > R) swap(L, R);  // 交换
	printf("%d %d %d\n", ans, L + 1, R); 
}

int main()
{
	while (sc("%d %d", &n, &m) && n + m) {
		init();
		for (int i = 1; i <= n; i++) {
			sc("%d", &c); sum += c;
			p[i].x = sum, p[i].id = i;
		}
		sort(p, p + n + 1, cmp);  // 排序,第一个也算上
		while (m--) {
			int tmp; sc("%d", &tmp);
			Solve(tmp);
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值