POJ - 2566 Bound Found(尺取法+前缀和)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ - 2566 Bound Found(尺取法+前缀和)相关的知识,希望对你有一定的参考价值。

题目链接:http://poj.org/problem?id=2566

题意:给定一个序列(n个整数)和一个整数k(m个),求出这个序列的一个子串,使之和的绝对值与k的差最小。

尺取法的题目有两个特性:

1. 所求的序列是一个连续的序列,这样才能将序列抽象成一个头和一个尾来描述。

2. 头尾枚举的序列满足某种单调的性质,这样才能进行尺取的操作。

这个序列是一个随意的序列,不可能直接对其进行操作,先要预处理下,进行前缀和操作,把对应的值和标记放在同一个pair。

然后根据前缀和的值进行排序,这样就符合尺取法的两个特性了。

其他的就是一些细节上的东西了。直接上代码,(•‾??‾?•)??°,

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int INF=0x3f3f3f3f;
 6 const int N=100011;
 7 pair <int,int> T[N];
 8 
 9 //前缀和初始化
10 void init(int n){
11     T[0]=make_pair(0,0);//这里需要放一个0,0进去,不然有一些值就取不到了. 
12     int x,tmp=0;
13     for(int i=1;i<=n;i++){
14         scanf("%d",&x);
15         tmp+=x;
16         T[i]=make_pair(tmp,i);
17     }
18     sort(T,T+n+1);
19 }
20 
21 int main(){
22     int n,m;
23     while(scanf("%d %d",&n,&m)){
24         if(n==0&&m==0) break;
25         init(n);
26         for(int i=1;i<=m;i++){
27             int l=0,r=1,t=INF;
28             int tmp,ansl,ansr,ans;
29             scanf("%d",&tmp);
30             while(r<=n&&t){
31                 int temp=T[r].first-T[l].first;
32                 if(abs(temp-tmp)<t){
33                     t=abs(temp-tmp);
34                     ans=temp;
35                     ansl=T[l].second;
36                     ansr=T[r].second;
37                 }
38                 if(temp<tmp) r++;
39                 if(temp>tmp) l++;
40                 if(temp==tmp) break;
41                 if(l==r) r++; //保证r>=l 
42             }
43             if(ansl>ansr) swap(ansl,ansr);//因为是经过排序过的,有可能左边的比右边的大. 
44             printf("%d %d %d\n",ans,ansl+1,ansr);//左边多加了一个0,需要+1 
45         }
46     }
47     return 0;
48 }

 

以上是关于POJ - 2566 Bound Found(尺取法+前缀和)的主要内容,如果未能解决你的问题,请参考以下文章

POJ - 2566 Bound Found(尺取法+前缀和)

尺取法好题POJ2566-Bound Found

poj 2566 Bound Found 尺取法

poj 2566 Bound Found

Bound Found POJ - 2566 (尺取好题)

Greedy:Bound Found(POJ 2566)