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;
}