• UVA1400"Ray, Pass me the dishes!"(线段树区间合并)


    wa成屎了。。。还是没过!

    -----------------------------

    过了!!!各种bug啊。。。刚才又瞄了一眼,发现移位多写了一个1。我草。fuck!

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

    分析:这个需要应用求最大连续子序列的分治算法:最优解要么完全在左半序列,要么完全在右半序列,要么跨越中点;

    构造一颗线段树,其中每个结点维护3个值:区间最大连续和max_sub(a,b),区间前缀最大连续和max_prefix(a,b),区间后缀最大连续和max_suffix(a,b)

    max_sub(a,b)=max(max_sub(a,m),max(max_sub(m+1,b),max_suffix(a,m)+max_preffix(m+1,b)));

    max_preffix(a,b)=max(max_preffix(a,m),max_preffix(m+1,b)+sum[m]-sum[a-1]);

    max_suffix(a,b)=max(max_suffix(m+1,b),max_suffix(a,m)+sum[b]-sum[m]);

    // File Name: 1400.cpp
    // Author: zlbing
    // Created Time: 2013/3/12 11:54:33
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,n) for(int i=0;i<n;i++)
    #define REP1(i,n) for(int i=1;i<n+1;i++)
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int MAXN = 511111;
    LL sum[MAXN<<2];
    LL Lsum[MAXN<<2];
    LL Rsum[MAXN<<2];
    int asum[MAXN<<2];
    int bsum[MAXN<<2];
    int bLsum[MAXN<<2];
    int aLsum[MAXN<<2];
    int aRsum[MAXN<<2];
    int bRsum[MAXN<<2];
    LL S[MAXN<<2];
    struct node{
        LL s;
        int a,b;
    };
    void PushUp(int rt,int m) {
        sum[rt]=max(sum[rt<<1],max(sum[rt<<1|1],Rsum[rt<<1]+Lsum[rt<<1|1]));
        if(sum[rt]==sum[rt<<1]){
            asum[rt]=asum[rt<<1];
            bsum[rt]=bsum[rt<<1];
        }else if(sum[rt]==Rsum[rt<<1]+Lsum[rt<<1|1]){
            asum[rt]=aRsum[rt<<1];
            bsum[rt]=bLsum[rt<<1|1];
        }else if(sum[rt]==sum[rt<<1|1]){
            asum[rt]=asum[rt<<1|1];
            bsum[rt]=bsum[rt<<1|1];
        }
    
        LL v1=S[bLsum[rt<<1]]-S[aLsum[rt<<1]-1];
        LL v2=S[bLsum[rt<<1|1]]-S[aLsum[rt<<1]-1];
        if(v1>=v2){
            Lsum[rt]=v1;
            aLsum[rt]=aLsum[rt<<1];
            bLsum[rt]=bLsum[rt<<1];
        }else{
            Lsum[rt]=v2;
            aLsum[rt]=aLsum[rt<<1];
            bLsum[rt]=bLsum[rt<<1|1];
        }
        v1=S[bRsum[rt<<1|1]]-S[aRsum[rt<<1|1]-1];
        v2=S[bRsum[rt<<1|1]]-S[aRsum[rt<<1]-1];
        if(v2>=v1){
            Rsum[rt]=v2;
            aRsum[rt]=aRsum[rt<<1];
            bRsum[rt]=bRsum[rt<<1|1];
        }else{
            Rsum[rt]=v1;
            aRsum[rt]=aRsum[rt<<1|1];
            bRsum[rt]=bRsum[rt<<1|1];
        }
    }
    void build(int l,int r,int rt) {
        if (l == r){
            sum[rt]=Lsum[rt]=Rsum[rt]=S[l]-S[l-1];
             asum[rt]=l;
             bsum[rt]=l;
             bLsum[rt]=l;
             aLsum[rt]=l;
             aRsum[rt]=l;
             bRsum[rt]=l;
            return ;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        PushUp(rt,r-l+1);
    }
    node query_prefix(int L,int R,int l,int r,int rt){
        node t;
        if(bLsum[rt]<=R){
            t.a=aLsum[rt];
            t.b=bLsum[rt];
            t.s=S[t.b]-S[t.a-1];
            return t;
        }
        int m=(l+r)>>1;
        if(R<=m)return query_prefix(L,R,lson);
        t=query_prefix(L,R,rson);
        t.a=l;
        t.s=S[t.b]-S[t.a-1];
        if(Lsum[rt<<1]>=t.s){
            t.s=Lsum[rt<<1];
            t.a=aLsum[rt<<1];
            t.b=bLsum[rt<<1];
        }
        return t;
    }
    node query_suffix(int L,int R,int l,int r,int rt){
        node t;
        if(aRsum[rt]>=L){
            t.a=aRsum[rt];
            t.b=bRsum[rt];
            t.s=S[t.b]-S[t.a-1];
            return t;
        }
        int m=(l+r)>>1;
        if(L>m)return query_suffix(L,R,rson);
        t=query_suffix(L,R,lson);
        t.b=r;
        t.s=S[t.b]-S[t.a-1];
        if(t.s<Rsum[rt<<1|1]){
            t.s=Rsum[rt<<1|1];
            t.a=aRsum[rt<<1|1];
            t.b=bRsum[rt<<1|1];
        }
        return t;
    }
    node query(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r){
            node temp;
            temp.a=asum[rt];
            temp.b=bsum[rt];
            temp.s=sum[rt];
            return temp;
        }
        int m=(l+r)>>1;
        if(R<=m)return query(L,R,lson);
        if(L>m)return query(L,R,rson);
        node t1=query(L,R,lson);
        node t2=query(L,R,rson);
        node t=t1;
        if(t.s<t2.s)t=t2;
        t1=query_prefix(L,R,rson);
        t2=query_suffix(L,R,lson);
        t1.a=t2.a;
        t1.s+=t2.s;
        if(t1.s==t.s){
            if(t.a>t1.a)t=t1;
        }else if(t1.s>t.s){
            t=t1;
        }
            return t;
    }
    
    int main(){
        int n,m;
        int cas=1;
        while(~scanf("%d%d",&n,&m)){
            int a,b;
            S[0]=0;
            REP1(i,n){
                scanf("%d",&a);
                S[i]=S[i-1]+a;
            }
            build(1,n,1);
            printf("Case %d:\n",cas++);
            REP(i,m){
                scanf("%d%d",&a,&b);
                node ans=query(a,b,1,n,1);
                printf("%d %d\n",ans.a,ans.b);
            }
        }
        return 0;
    }
    // LA3938 Ray, Pass me the dishes!
    // Rujia Liu 正确代码
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 500000 + 10;
    const int maxnode = 1000000 + 10;
    typedef long long LL;
    typedef pair<int,int> Interval;
    
    LL prefix_sum[maxn];
    
    LL sum(int L, int R) {
      return prefix_sum[R] - prefix_sum[L-1];
    }
    
    LL sum(Interval p) {
      return sum(p.first, p.second);
    }
    
    Interval better(Interval a, Interval b) {
      if(sum(a) != sum(b)) return sum(a) > sum(b) ? a : b;
      return a < b ? a : b; // 利用pair自带的字典序
    }
    
    int qL, qR;
    
    struct IntervalTree {
      int max_prefix[maxnode];
      int max_suffix[maxnode];
      Interval max_sub[maxnode];
    
      void build(int o, int L, int R) {
        if(L == R) {
          max_prefix[o] = max_suffix[o] = L;
          max_sub[o] = make_pair(L, L);
        } else {
          int M = L + (R-L)/2;
          // 递归创建子树
          int lc = o*2, rc = o*2+1;
          build(lc, L, M);
          build(rc, M+1, R);
    
          // 递推max_prefix
          LL v1 = sum(L, max_prefix[lc]);
          LL v2 = sum(L, max_prefix[rc]);
          if(v1 == v2) max_prefix[o] = min(max_prefix[lc], max_prefix[rc]);
          else max_prefix[o] = v1 > v2 ? max_prefix[lc] : max_prefix[rc];
    
          // 递推max_suffix
          v1 = sum(max_suffix[lc], R);
          v2 = sum(max_suffix[rc], R);
          if(v1 == v2) max_suffix[o] = min(max_suffix[lc], max_suffix[rc]);
          else max_suffix[o] = v1 > v2 ? max_suffix[lc] : max_suffix[rc];
    
          // 递推max_sub      
          max_sub[o] = better(max_sub[lc], max_sub[rc]); // 完全在左子树或者右子树
          max_sub[o] = better(max_sub[o], make_pair(max_suffix[lc], max_prefix[rc])); // 跨越中线
        }
      }
    
      Interval query_prefix(int o, int L, int R) {
        if(max_prefix[o] <= qR) return make_pair(L, max_prefix[o]);
        int M = L + (R-L)/2;
        int lc = o*2, rc = o*2+1;
        if(qR <= M) return query_prefix(lc, L, M);
        Interval i = query_prefix(rc, M+1, R);
        i.first = L;
        return better(i, make_pair(L, max_prefix[lc]));
      }
    
      Interval query_suffix(int o, int L, int R) {
        if(max_suffix[o] >= qL) return make_pair(max_suffix[o], R);
        int M = L + (R-L)/2;
        int lc = o*2, rc = o*2+1;
        if(qL > M) return query_suffix(rc, M+1, R);
        Interval i = query_suffix(lc, L, M);
        i.second = R;
        return better(i, make_pair(max_suffix[rc], R));
      }
    
      Interval query(int o, int L, int R) {
        if(qL <= L && R <= qR) return max_sub[o];
        int M = L + (R-L)/2;
        int lc = o*2, rc = o*2+1;
        if(qR <= M) return query(lc, L, M);
        if(qL > M) return query(rc, M+1, R);
        Interval i1 = query_prefix(rc, M+1, R); // 右半的前缀
        Interval i2 = query_suffix(lc, L, M); // 左半的后缀
        Interval i3 = better(query(lc, L, M), query(rc, M+1, R));
        return better(make_pair(i2.first, i1.second), i3);
      }
    };
    
    IntervalTree tree;
    
    int main() {
      int kase = 0, n, a, Q;
      while(scanf("%d%d", &n, &Q) == 2) {
        prefix_sum[0] = 0;
        for(int i = 0; i < n; i++) {
          scanf("%d", &a);
          prefix_sum[i+1] = prefix_sum[i] + a;
        }
        tree.build(1, 1, n);
        printf("Case %d:\n", ++kase);
        while(Q--) {
          int L, R;
          scanf("%d%d", &L, &R);
          qL = L; qR = R;
          Interval ans = tree.query(1, 1, n);
          printf("%d %d\n", ans.first, ans.second);
        }
      }
      return 0;
    }
  • 相关阅读:
    一张图带你了解数据分析的完整流程,建议收藏
    【Unnatural × Lemon × 武汉】如果病毒结束了,你最想干什么事
    两万字深度介绍分布式系统原理!【收藏版】
    ETL的基础知识,看完你就全明白了!
    Java最大不重复子串
    一文速懂利用python字典的引用传递实现循环套娃(嵌套)
    ETSI GS MEC 015,MEP 带宽管理 API
    laravel 5.5 ajax返回错误信息
    laravel 5.5 ajax返回错误信息
    从实践出发:微服务布道师告诉你Spring Cloud与Boot他如何选择
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2958212.html
Copyright © 2020-2023  润新知