poj2566(尺取模型)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值