zoukankan      html  css  js  c++  java
  • UVA-1400 Ray, Pass me the dishes!

    UVA-1400 Ray, Pass me the dishes!

    题意:给出一个长度为n的整数序列D,有m个询问,每个询问(a,b)找到两个下标x和y,使得a<=x<=y<=n,并且Dx+...+Dy尽量大。如果有多组满足条件的x和y,x应该尽量小。如果还有多解,y应该尽量小。

    思路:线段树,对于一个区间,需要维护的值是这个区间的最大连续前缀和,后缀和以及最大连续和的数字下标出现位置。这样,当找(a,b)的最大连续和的下标位置时,分三种情况:

    1:最大连续和的起点和终点都在[a,mid)中

    2:连续和的起点终点都在[mid,b)中

    3:起点在[a,mid)中,终点在[mid,b)中,这样最大连续和就是以mid为终点的[a,mid)的后缀和+以mid为起点的[mid,b)的前缀和,递归查找连续和的起点终点即可。

    具体参考《算法竞赛入门经典——训练指南》P202

    AC代码:

    #define _CRT_SECURE_NO_DEPRECATE
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <map>
    #include <algorithm>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define MAX 0x7ffffffffffffff
    typedef long long ll;
    const int N_MAX = 500000+20;
    int D[N_MAX];
    ll presum[N_MAX];
    int n, m;
    struct MAX_sum {
        ll data;int L, R;
        MAX_sum(ll data = 0, int L = 0, int R = 0) :data(data), L(L), R(R) {}
    }max_sum[2 * N_MAX];
    struct MAX_prefix {
        ll data;int R;
        MAX_prefix(ll data = 0, int R = 0) :data(data), R(R) {}
    }max_prefix[2 * N_MAX];
    struct MAX_suffix {
        ll data;int L;
        MAX_suffix(ll data = 0, int L = 0) :data(data), L(L) {}
    }max_suffix[2 * N_MAX];
    
    ll sum(int l,int r) {//计算区间[l,r)的和
        if (l == 0)return presum[r-1];
        else return presum[r-1] - presum[l - 1];
    }
    
    MAX_sum better(MAX_sum a,MAX_sum b) {
        if (a.data != b.data)return a.data > b.data ? a : b;
        else if (a.L != b.L)return a.L < b.L ? a : b;
        else return a.R < b.R ? a : b;
    }
    
    void segtree_init(int k, int l, int r) {//区间[l,r)
        if (r - l == 1) {
            max_prefix[k] = MAX_prefix(D[l], l);
            max_suffix[k] = MAX_suffix(D[l], l);
            max_sum[k] = MAX_sum(D[l], l, l);
        }
        else {
            int mid = (l + r) >> 1, chl = (k << 1) + 1, chr = (k << 1) + 2;
            segtree_init(chl, l, mid);
            segtree_init(chr, mid, r);
            
            if (max_prefix[chl].data >= sum(l,mid) + max_prefix[chr].data)
                max_prefix[k] = max_prefix[chl];
            else max_prefix[k] = MAX_prefix(sum(l,mid) + max_prefix[chr].data, max_prefix[chr].R);
            if (max_suffix[chr].data > max_suffix[chl].data + sum(mid,r))
                max_suffix[k] = max_suffix[chr];
            else max_suffix[k] = MAX_suffix(sum(mid,r) + max_suffix[chl].data, max_suffix[chl].L);
            max_sum[k] = better(max_sum[chl],max_sum[chr]);
            max_sum[k] = better(max_sum[k], MAX_sum(max_suffix[chl].data + max_prefix[chr].data, max_suffix[chl].L, max_prefix[chr].R));
        }
    }
    
    MAX_prefix seg_pre_query(int a, int b, int k, int l, int r) {
        if (a <= l&&b >= r) {
            return max_prefix[k];
        }
        else if (a >= r || b <= l) {//完全不相交
            return MAX_prefix(-MAX, INF);
        }
        else {
          int chl = (k << 1) + 1, chr = (k << 1) + 2, mid = (l + r) >> 1;
          MAX_prefix  p1=seg_pre_query(a, b, chl, l, mid);
          MAX_prefix  p2=seg_pre_query(a, b, chr, mid, r);
          return p1.data >= p2.data + sum(l, mid) ? p1 : MAX_prefix(p2.data + sum(l, mid), p2.R);
        }
    }
    
    MAX_suffix seg_suf_query(int a,int b,int k,int l,int r) {
        if (a <= l&&b >= r) {
            return max_suffix[k];
        }
        else if (a >= r || b <= l) {
            return MAX_suffix(-MAX,INF);
        }
        else {
            int chl = (k << 1) + 1, chr = (k << 1) + 2, mid = (l + r) >> 1;
            MAX_suffix  p1 = seg_suf_query(a, b, chl, l, mid);
            MAX_suffix  p2 = seg_suf_query(a, b, chr, mid, r);
            return p2.data > p1.data + sum(mid, r) ? p2 : MAX_suffix(p1.data + sum(mid, r), p1.L);
        }
    }
    
    MAX_sum  seg_query(int a, int b, int k, int l, int r) {
        if (a <= l&&b >= r) {
            return max_sum[k];
        }
        else if (a >= r || b <= l) {//完全不相交
            return MAX_sum(-MAX,INF,INF);
        }
        else {
            int mid = (l + r) >> 1, chl = (k << 1) + 1, chr = (k << 1) + 2;
            MAX_sum sum1 = seg_query(a, b, chl, l, mid);
            MAX_sum sum2 = seg_query(a, b, chr,mid, r);
            MAX_prefix pre = seg_pre_query(a, b, chr, mid, r);//mid一定在[a,b)区间当中
            MAX_suffix suf = seg_suf_query(a, b, chl, l, mid);//同理
            MAX_sum sum3 = MAX_sum(pre.data + suf.data, suf.L, pre.R);
            MAX_sum SUM = better(sum1, sum2);
            SUM = better(SUM,sum3);
            return SUM;
        }
    }
    
    int main() {
        int Case = 0;
        while (scanf("%d%d",&n,&m)!=EOF) {
            for (int i = 0; i < n; i++) {
                scanf("%d", &D[i]);
                if (!i)presum[i] = D[i];
                else presum[i] = presum[i - 1] + D[i];
            }
            segtree_init(0,0,n);
            printf("Case %d:
    ",++Case);
            for (int cs = 1; cs <= m; cs++) {
                int a, b; scanf("%d%d", &a, &b); a--;
                MAX_sum ans=seg_query(a,b,0,0,n);
                printf("%d %d
    ",ans.L+1,ans.R+1);
            }
        }
        return 0;
    }
    
    /*
    8 1
    3 -4 1 3 -2 5 1 3
    2 6
    */

     

  • 相关阅读:
    TweenLite简单运用
    nodejs 重定向 (redirect + writeHead(Location))
    Nodejs Web模块( readFile 根据请求跳转到响应html )
    Express框架(http服务器 + 路由)
    AI 学习路线
    implicitly_wait()隐式等待
    Python 爬虫基础Selenium
    Selenium2+python自动化15-select下拉框
    python selenium while 循环
    jupyter notebook修改默认路径和浏览器
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/9123820.html
Copyright © 2011-2022 走看看