zoukankan      html  css  js  c++  java
  • POJ 2566 Bound Found(尺取前缀和)

    题目链接
    题目大意:有(m)次询问, 每次要求在一个长度为(n)的序列中找出一个区间其和的绝对值与给出的数最接近。(这题有spj,如有多解输出其一即可)。
      题目看上去像是尺取的题,但是因为序列中既有正数又有负数,所以其区间和是不具有单调性的,直接尺取显然是无从下手的。不过既然问题问的是区间还是有办法让序列具有单调性的。如果对该序列取前缀和,然后让前缀和从小到大排序,那么这个前缀和序列的差就有了单调性。假如按从小到大排序,对于前缀和(a_i)(a_j)(i<j)(j)越大(i)越小,其差值就越大,也就是区间和的绝对值越大。
      但是需要注意一点的是,尺取的初位置选择。假设对前缀和序列从小到大排序,对于一段负的前缀和序列来说,应该从最小的前缀和开始尺取,这样(r)越大,其尺取的区间和的绝对值也就越大,(l)越小,其尺取的区间和的绝对值也就越小,当尺取到(0)时,表示从第一个位置开始进行尺取到某个位置。而对于一段正的前缀和序列,应该从(0)开始尺取,表示从第一个位置进行尺取到某个位置。如果对负数序列也从(0)开始尺取的话,就会出现(r)越大,区间和的绝对值越小,(l)越小区间和的绝对值越大的情况。所以我们每次在排序之前在前缀和序列中加入一个(0)元素,就能让前缀和序列无论是否有负数都具有一致性。感觉好难解释啊,实在不懂就看代码意会吧。。。

    const int maxn = 1e5+10;
    int n, m;
    struct PRE {
        int num;int val;
        bool operator < (const PRE &a) const {
            return val<a.val;
        }
    } pre[maxn];
    int main(void) {
        while(~scanf("%d%d", &n, &m) && (n||m)) {
            pre[0].val = pre[0].num = 0;
            for (int i = 1; i<=n; ++i) {
                scanf("%d", &pre[i].val);
                pre[i].val+=pre[i-1].val; pre[i].num = i; 
            }
            sort(pre, pre+n+1);
            while(m--) {
                int t, l = 0, r = 1, ans, ansl, ansr, minn = INF;
                scanf("%d", &t);
                while(r<=n) {
                    int d = abs(pre[r].val - pre[l].val);
                    if (minn >= abs(d-t)) {
                        minn = abs(d-t);
                        ans = d;
                        ansl = pre[l].num;
                        ansr = pre[r].num;
                    }
                    if (d<=t) ++r;
                    else ++l;
                    if (l==r) ++r; //避免上一步出现l==r然后minn因此更新成0的情况,前缀和求区间相减的两个前缀和必不相等,除非是空区间
                }
                if (ansl>ansr) swap(ansl, ansr);
                printf("%d %d %d
    ", ans, ansl+1, ansr); 
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Jenkins结合.net平台综合应用之通过SSH方式拉取代码
    Jenkins结合.net平台综合之监听git仓库并自动摘取最新代码编译
    XCode插件因为升级不能用了怎么办?几个步骤教你搞定
    如何写一个FMDB帮助类?看看runtime吧
    ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(五) 补充:历史记录 和 消息提醒
    【转】iOS的APP资源,开源的哦
    活到老学到老:iOS开发中的基础知识(一)
    融云SDK:获取用户Token的方法
    对接融云即时通讯组件SDK,轻松实现App聊天室
    【iOS】那些年,遇到的小坑
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12739951.html
Copyright © 2011-2022 走看看