POJ - 2566 Bound Found (尺取法)

题目链接

题意: 给你一串数,有正有负。 再给你m 个数,每个数t[i] , 求最接近 t[i] 的一个区间,区间的值是绝对值。

一看这题没有什么思路,因为前缀和并不是递增的,要怎么办呢?

想一想,绝对值,和顺序并没有什么关系,所以我们可以给前缀和排个序,从小到大排序,然后在进行尺取。

要注意的是我们找  [l,r] 区间的值,就要是 sum[r] - sum[l-1], 这个时候,如果要从 1 开始,我们就要有sum[0], 

所以排序的时候一定要把 sum[0] 加进去。

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 5e5;
struct node{
    int b;
    int a;
    bool operator < (const node &now)const{
        return a<now.a;
    }
}f[N];
int n,m;
int main() {
    int   z;
    while(scanf("%d%d",&n,&m)==2 && n != 0){
        f[0].a = 0; f[0].b = 0;
        for (int i = 1; i <= n; i++){
            scanf("%d",&z);
            f[i].a = f[i-1].a + z;
            f[i].b = i;
        }
        sort(f ,f + n + 1);
        int x,y;
        int  tt,tot,t,val;
        for (int i = 0; i < m; i++){
            scanf("%d",&t);
            x = 1; y = 1;
            val = 1 << 30;
            int l = 0,r = 1;
                while(r <= n && val > 0){
                     tot = abs(f[r].a - f[l].a);
                     if (abs(tot - t) < val){
                         tt = tot;
                         val = abs(tt - t);
                         x = min(f[l].b,f[r].b);
                         y = max(f[l].b,f[r].b);
                     }
                     if (tot < t) r++;
                     if (tot > t) l++;
                     if (l == r) r++;
                }
            printf("%d %d %d\n",tt,x+1,y);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/kidsummer/article/details/81213723