http://poj.org/problem?id=2566
开始看到这道题时不会做,看了题解才会的,由于原序列散乱,不知道怎么加才能最大,而尺取法要在序列有序才能进行,所以可以用前缀和来使序列单调。定义pair<ilong,long> ss前面记录千缀合,后面记录编号,然后根据千缀合进行大小排序,sort默认按ss.first从大到小排序的,所以有了单调性
所以,ss[j].first-ss[i].first就是从ss[i].second到ss[j].second的和,令l=0,r=1
若ss[r].first-ss[l].first大于t,则l++,小于t则r++,等于t时,ss[l].second,ss[r].second就是左右端点
如果l==r时r++,序列不能为空
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<cmath>
#define INF 0x3f3f3f3f
#define ll long long
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define DEBUG cout<<endl<<"DEBUG"<<endl;
using namespace std;
typedef pair<ll, ll> p;
ll n, k, arr[100010], t;
p ss[100010];
ll abss(ll x) {
return x < 0 ? -x : x;
}
int main() {
while(cin >> n >> k && (n + k)) {
ss[0] = p(0, 0);
for(int i = 1; i <= n; i++)
cin >> arr[i], ss[i] = p(ss[i - 1].first + arr[i], i);
sort(ss, ss + n + 1);
for(int i = 1; i <= k; i++) {
cin >> t;
ll l = 0, r = 1, x, y, s, cha = INF;
while(r <= n) {
ll b = ss[r].first - ss[l].first;
if(abss(t - b) < cha) {
cha = abss(t - b);
s = b;
x = ss[l].second;
y = ss[r].second;
}
if(b > t)
l++;
else if(b < t)
r++;
else
break;
if(l == r)
r++;
}
if(y < x)
swap(y, x);
cout << s << " " << x + 1 << " " << y << endl;
}
}
return 0;
}