POJ 2566 Bound Found

题意 : 给你n个数字,这些数字可正可负,再给你个数字t,
求在这个数列中一个连续的子序列,和的绝对值 与t相差最小;

数据范围较大, 考虑数字没有负数的情况,
能够想到用尺取法解决, (关于尺取法, 自己感受一下这东西的奇妙, 不好说, 理解了之后也没什么好说, 实现主要是首尾指针的移动), 那么增加了负数之后, 发现题目中要的是序列的绝对值, 发现直接排序前缀和即使用后面的前缀和减去前面的前缀和, 也没有关系;

但主要需要注意的是本题细节比较烦, 在POJ上WA了3,4次, 这里提示一下
注意如果给出的值为0时的处理, 还有就是自己多想几组小数据来调试, 调的很恶心, 但也很享受, 适合做尺取的好题

/*
*题意:给你n个数字,这些数字可正可负,再给你个数字t,
*求在这个数列中一个连续的子序列,和的绝对值 与t相差最小
*                                        ————Galaxy TODO
*/
#include <cstdio>
#include <algorithm>

typedef long long LL;

const int N = 1e5 + 10;
#define C c = getchar()
#define rep(i, s, t) for(int i = s; i <= t; ++i)

LL abs(LL x) {return x>0?x:-x;}
int read(int x=0, int t=1) {char C;
    while(c<'0' || c>'9') {if(c=='-') t=-1; C;}
    while(c>='0' && c<='9') x = x*10 + c-'0', C;
    return x*t;
}

struct Sum_tot{
    LL sum; int rk;
    //Sum_tot(int _sum, int _rk) {sum = _sum; rk = _rk;}
    bool operator < (const Sum_tot& rhs) const{
        return sum < rhs.sum;
    }
}P[N];

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
    freopen("res.out", "w", stdout);
#endif
    int n, T; LL S;
    while(scanf("%d%d", &n, &T) == 2 && n+T) {
        P[0].sum = 0, P[0].rk = 0;
        rep(i, 1, n) P[i] = ((Sum_tot) {P[i-1].sum+read(), i});

        std :: sort(P, P+n+1);
    //  rep(i, 0, n) printf("%lld%c", P[i].sum, i^n?' ':'\n');

        while(T--) {
            scanf("%lld", &S);
            int ansl=n, ansr=n;
            int l = n-1, r = n;
            LL res = 1LL << 62;
            while(r > l) {
        //      printf("%d %d__debug1\n", l, r);
                while(P[r].sum - P[l].sum <= S && l >= 0) { 
                    if(abs(P[r].sum-P[l].sum-S) < abs(S-res)) {
                        res = P[r].sum - P[l].sum;
                        ansl = P[l].rk, ansr = P[r].rk;
                    }
                    --l;
                }
                if(l < 0) break;
    //          printf("%d %d__debug2\n", l, r);

                while(P[r].sum - P[l].sum >= S && r > l) { 
                    if(P[r].sum-P[l].sum-S < abs(res-S)) {
                        res = P[r].sum - P[l].sum;
                        ansl = P[l].rk, ansr = P[r].rk;
                    }
                    --r;
                }
                if(r < 0) break;
                if(l == r) --l;
                if(l < 0) break;
        //      printf("%d %d__debug3\n", l, r);
                if(res == S) break;
            }
            if(ansl+1 > ansr) std::swap(ansl, ansr);
            printf("%lld %d %d\n", res, ansl+1, ansr);
        }
    }
    return 0;
}
//XXX
posted @ 2016-11-15 13:16  pbvrvnq  阅读(80)  评论(0编辑  收藏  举报