/*
translation:
给出一串数列,求其中最接近t的一个子串之和是多少?
solution:
尺取法。
这道题不能直接对原数组采用尺取,因为原来的数组有正有负。而尺取法使用的条件就是在推进的过程中的单调性,
如果对原数组直接采取尺取,由于原数组正负数都有,导致在推进过程中尺取的和有增加也有减少。故不能采取尺取。
所以考虑对前缀进行排序后,再进行尺取即可。
note:
date:
2016.11.13
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100005;
const int INF = 1e30;
int a[maxn], n, k, t;
int sum[maxn]; //sum[i]:= 1~i 's sum (inclusive)
pair<int, int> p[maxn];
void solve(int t)
{
int l = 0, r = 1;
int ans = INF, ans_l;
int ans_r, tmp = INF;
while(l <= n && r <= n){
int d = p[r].first - p[l].first;
if(abs(d - t) < tmp){
tmp = abs(d - t);
ans = abs(d);
ans_l = p[l].second;
ans_r = p[r].second;
}
if(d > t) l++;
else if(d < t) r++;
else break;
if(l == r) r++;
}
if(ans_r < ans_l) swap(ans_r, ans_l);
printf("%d %d %d\n", ans, ans_l + 1, ans_r);
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &k)){
if(n == 0 && k == 0) break;
p[0] = make_pair(0, 0);
for(int i = 1; i <= n; i++){
scanf("%d", &p[i].first);
p[i].first += p[i-1].first;
p[i].second = i;
}
sort(p, p + n + 1);
while(k--){
scanf("%d", &t);
solve(t);
}
}
return 0;
}
poj2566(尺取模型)
最新推荐文章于 2022-03-22 11:00:46 发布