Bound Found POJ - 2566

原题链接
考察:双指针
错误思路:
  贪心,对于当前枚举\(a[i]\),要么把它加入到当前和里,要么新开一个和.
错误原因:
  只能说当前差值大不代表以后小.
正确思路:
  双指针法用于解决有单调性的区间问题.这里找到区间和的绝对值最靠近t的点.因为数列是有+-的,所以前缀和没有单调性,但是这里求的是绝对值,所以l,r哪个大并没有影响.可以将前缀和数组排序,找到两个差值最靠近t的\(ansl,ansr\)

Code

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010,INF = 0x3f3f3f3f;
int n,m,a[N],t;
struct Node{
	int sum,idx;
	bool operator<(const Node& s)const{
		return this->sum<s.sum;
	}
}node[N];
//void solve()
//{
//	int res = INF,l = 1,r = 1;
//	LL sum = 0,ans = 0;
//	for(int i=1;i<=n;i++)
//	{
//		LL temp = abs(sum+a[i])-t;
//		if(abs(temp)<res)
//		{
//			res = abs(temp);
//			sum+=a[i];
//			r = i;
//			ans = abs(sum);
//		}else if(abs(abs(a[i])-t)<res)
//		{
//			res = abs(abs(a[i])-t);
//			sum = a[i];
//			l = r = i;
//			ans = abs(sum);
//		}else sum = 0;
//	}
//	printf("%lld %d %d\n",ans,l,r);
//}
void solve() 
{
	int res = INF,l = 0,r = 1;
	int ansl=1,ansr=2,ans;
	while(r<=n&&res)
	{
		int temp = node[r].sum-node[l].sum;
		if(abs(temp-t)<res)
		{
			res = abs(temp-t);
			ans = temp;
			ansl = node[l].idx,ansr = node[r].idx;
		}
		if(temp>t) l++;
		if(temp<t) r++;
		if(l>=r) r++;
	}
	if(ansl>ansr) swap(ansl,ansr);
	printf("%d %d %d\n",ans,ansl+1,ansr);
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF&&(n+m))
	{
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		node[0].sum = node[0].idx = 0;
		for(int i=1;i<=n;i++)
		{
			node[i].sum = node[i-1].sum +a[i];
			node[i].idx = i;
		}
		sort(node,node+n+1);
		while(m--)
		{
			scanf("%d",&t);
			solve();
		}
	}
	return 0;
}

posted @ 2021-06-28 15:58  acmloser  阅读(27)  评论(0编辑  收藏  举报