POJ-2566Bound Found(尺取法)(好题)

来源:互联网 发布:bl国产网络剧 编辑:程序博客网 时间:2024/06/05 14:55
题意:


给你n个数的数列。和k个询问。

每个询问给你一个数t。求连续的数列和。使其与t的差的绝对值最小。输出这个连续和的绝对值。并且输出这个连续和的左端点和右端点。

参考博客:点击打开链接

思路:完全没思路,看了题解后。是一道好题。对尺取法的理解更深了。


尺取法在选和舍的过程中,必须满足某种单调性,不然这种选和舍是没有意义的。刚开始我直接把尺取法套在原数组上是没有用的(因为无法确定继续选和舍的那个临界条件)


题解的思路:


计算前缀和(注意要加1个0,可能从头开始),然后pair用来记录前缀和与其下标。
再sort一下。




这样,继续选和舍的条件就可以确定了。因为 temp=sum[s].fs-sum[f].fs;,f不变的情况下temp随s是递增的,并且可以根据temp与t的大小选与舍。时刻保持s>f


#include <iostream>#include <map>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>#include <stack>#include <functional>#include <set>#include<sstream>#include <cmath>using namespace std;#define pb push_back#define PB pop_back#define bk back()#define fs first#define se second#define INF 1e10;#define sq(x) (x)*(x)#define eps (1e-10)#define clr(x) memset((x),0,sizeof (x))#define cp(a,b) memcpy((a),(b),sizeof (b))typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> P;const int maxn=100100;P sum[maxn];int main(){    int n,k,t,num;    while(cin>>n>>k&&n&&k)    {        sum[0]=make_pair(0,0);        for(int i=1;i<=n;i++)        {            cin>>num;            sum[i]=make_pair(sum[i-1].fs+num,i);        }        sort(sum,sum+n+1);        while(k--)        {            cin>>t;            int res=INF;            int f=0,s=1,temp=0,v,le,ri;            for(;;)            {                temp=sum[s].fs-sum[f].fs;                if(abs(temp-t)<res)                {                    res=abs(temp-t);                    v=temp;                    le=sum[f].se;                    ri=sum[s].se;                }                if(temp<t) s++;                else         f++;                if(s==f)     s++;                if(s>n) break;            }            cout<<v<<" "<<min(le,ri)+1<<" "<<max(le,ri)<<endl;        }    }    return 0;}


0 0