您的位置:首页 > 运维架构

[POJ 2566] Bound Found (TwoPointer入门)

2016-04-13 21:47 281 查看
POJ - 2566

给你一组数,要求从中找出连续的一段,使得其和的绝对值尽量和 t接近

这种求序列连续一段的情况,最适合使用 two_pointer的技巧了

不过 two_pointer的前提是,序列在某种意义上是单调的

不过这题难就难在序列里数可正可负,时大时小,所以并不能使用 two_pointer

关键步骤,求出前缀和,再对前缀和排序

由于求的是绝对值,那么 sum[r]-sum[l]==sum[l]-sum[r]

所以对前缀和排序不影响结果

预处理出前缀和,然后连同 0位置的前缀和一起从小到大排序,这样序列就单调了

问题就归约成了单调序列中两个不相同的数相减,从而可以使用 two_pointer

注意点:

1) 要将 0位置的前缀和一起排序

2) 由于序列不能为空,所以必须是两个位置不相同的前缀和相减

3) sum[r]-sum[l]求出来的是 [l+1, r]的,所以最后输出的时候 l还要加一

实际上,two_pointer是一种较为机智的暴力

而且很多 two_pointer由于需要单调性,所以用二分也可以做

而且不知怎的,我从 two_pointer联想到了莫队算法 = =

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Pow2(a) (a*a)

const int maxn=1e5+10,INF=0x3f3f3f3f;
int N,K;
Pii inpt[maxn];

bool pcmp(Pii u, Pii v){return u.first<v.first;}

int main()
{
while(~scanf("%d%d",&N,&K)&&N)
{
for(int i=1; i<=N; i++)
{
scanf("%d", &inpt[i].first);
inpt[i].first+=inpt[i-1].first;
inpt[i].second=i;
}
inpt[N+1].first=0;inpt[N+1].second=0;
sort(inpt+1,inpt+1+N+1,pcmp);
for(int i=1; i<=K; i++)
{
int t;
scanf("%d", &t);
int sp=1,tp=1,delt=INF,ans,ansl,ansr;
for(sp; sp<=N+1; sp++)
{
if(tp<=sp) tp=sp+1;
for(tp; tp<=N+1; tp++)
{
int val=inpt[tp].first-inpt[sp].first;
if(abs(val-t)<delt)
{
delt=abs(val-t);
ans=val;
ansl=inpt[sp].second;
ansr=inpt[tp].second;
}
if(val>t) break;
}
}
printf("%d %d %d\n", ans, min(ansl,ansr)+1, max(ansl,ansr));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: