题目来源:http://poj.org/problem?id=2566
刚开始做的时候没什么思路,看别人的博客学会的:https://www.cnblogs.com/iiyiyi/p/5962512.html
因为所需的是区间的为绝对值,所以sum[r] - sum[l-1] == sum[l-1] - sum[r] 。因此只需要找合适的<l,r>。
当前缀和为有序时,尺取法可以得到最优解。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=1e5+10;
struct Data {
int num, pos;
bool operator<(const Data &x) const {
return num < x.num;
}
};
int n,k,a[maxn];
Data s[maxn];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (cin >> n >> k) {
if (n == 0 && k == 0)break;
memset(s, 0, sizeof(s));
for (int i = 1; i <= n; ++i) {
cin >> a[i];
s[i].num = s[i - 1].num + a[i];
s[i].pos = i;
}
sort(s, s + 1 + n);
for (int i = 1; i <= k; ++i) {
int t, l = 0, r = 1, ans, mans = 2e9, ansl, ansr;
cin >> t;
while (r <= n) {
int x = s[r].num - s[l].num;
if (abs(x - t) < mans) {
mans = abs(x - t);
ans = x;
ansl = s[l].pos;
ansr = s[r].pos;
}
if (x == t)break;
if (x < t)++r;
if (x > t)++l;
if (l == r)++r;
}
cout << ans << ' ' << min(ansr, ansl) + 1 << ' ' << max(ansl, ansr) << endl;
}
}
return 0;
}