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