题目链接
题意: 给你一串数,有正有负。 再给你m 个数,每个数t[i] , 求最接近 t[i] 的一个区间,区间的值是绝对值。
一看这题没有什么思路,因为前缀和并不是递增的,要怎么办呢?
想一想,绝对值,和顺序并没有什么关系,所以我们可以给前缀和排个序,从小到大排序,然后在进行尺取。
要注意的是我们找 [l,r] 区间的值,就要是 sum[r] - sum[l-1], 这个时候,如果要从 1 开始,我们就要有sum[0],
所以排序的时候一定要把 sum[0] 加进去。
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 5e5;
struct node{
int b;
int a;
bool operator < (const node &now)const{
return a<now.a;
}
}f[N];
int n,m;
int main() {
int z;
while(scanf("%d%d",&n,&m)==2 && n != 0){
f[0].a = 0; f[0].b = 0;
for (int i = 1; i <= n; i++){
scanf("%d",&z);
f[i].a = f[i-1].a + z;
f[i].b = i;
}
sort(f ,f + n + 1);
int x,y;
int tt,tot,t,val;
for (int i = 0; i < m; i++){
scanf("%d",&t);
x = 1; y = 1;
val = 1 << 30;
int l = 0,r = 1;
while(r <= n && val > 0){
tot = abs(f[r].a - f[l].a);
if (abs(tot - t) < val){
tt = tot;
val = abs(tt - t);
x = min(f[l].b,f[r].b);
y = max(f[l].b,f[r].b);
}
if (tot < t) r++;
if (tot > t) l++;
if (l == r) r++;
}
printf("%d %d %d\n",tt,x+1,y);
}
}
return 0;
}