(POJ) 2566 Bound Found (尺取法)

题目大意:就是在给你的数列中取一段,使它和的绝对值最接近于t,并输出他的和的绝对值,区间l和r。

解题思路:一开始说这是一道尺取题,我是不信的,因为没有发现单调性,那我怎么尺取呢,看了别人的题解,才恍然大悟,居然可以对前缀和sum排序,当然下标id是要记住的。然后这时候的sum就有单调性了,我们就可以在sum上进行尺取。l与r,a[r].sum-a[l].sum 就是 a[l].id+1与a[r].id对应的区间的和的绝对值(因为求的是绝对值嘛,那就可以直接大的减小的,和小的减大的取绝对值同效果),如果a[r].sum-a[l].sum>t, l++,反之 r++,并且每次尝试更新。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=1e5+7;
struct node {
	int id,sum;
} a[maxn];
int n,k,t;
bool cmp(node x,node y) {
	return x.sum<y.sum;
}
void solve() {
	int l = 0, r = 1, al, ar, ans, minn = inf;
	while (l<=n && r<=n && minn!=0) {
		int temp=a[r].sum-a[l].sum;//这里不能用算的时候 l-1 因为这里的l是排序后的数组,已经没有前后逻辑关系
		if (abs(temp-t) < minn) {
			minn=abs(temp-t);
			ar=a[r].id,al=a[l].id;
			ans=temp;
		}
		if (temp > t)	l++;
		else if (temp < t)	r++;
		else	break;
		if (r == l)	r++;
	}
	if(al>ar)	swap(al,ar);
	cout<<ans<<" "<<al+1<<" "<<ar<<endl; //最后再将al+1  
}

int main() {
	while(scanf("%d%d",&n,&k)!=EOF) {
		if(!n && !k)	break;
		a[0].sum=0,a[0].id=0; //这里0要加进去,因为算的时候不能l-1了 
		for(int i=1; i<=n; ++i) {
			scanf("%d",&a[i].sum);
			a[i].sum+=a[i-1].sum;
			a[i].id=i;
		}
		sort(a,a+1+n,cmp);
		while(k--) {
			scanf("%d",&t);
			solve();
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值