zoukankan      html  css  js  c++  java
  • dp + 预处理前缀和

    Equator 

    Problem's Link:  http://acm.hnu.cn/online/?action=problem&type=show&id=13248&courseid=0


     

    Mean: 

    给你n个数,让你求n个数的最大环状子段和。

    analyse:

    经典题型。

    我们知道,环状最大子段和要么在[0...n-1]中,要么在两端。

    第一种情况很好办,用最大子段和的普通求法O(n)扫一遍就行。

    第二种情况:首先我们预处理出两个数组:

    zz[i]:表示从最左边第0个起,到i的最大和。

    ff[i]:表示从最右边n-1个起,到n-i-1的最大和。

    这样我们只需简单的枚举一下i,求zz[i]+ff[i+1]的最大值即可。也就相当于求sum[0...i]+sum[i+1...n-1]的最大值。

    最后比较一下两种情况的最大值即可。

    Time complexity: O(N)

     

    Source code:

    /*
    * this code is made by crazyacking
    * Verdict: Accepted
    * Submission Date: 2014-04-03-21.21
    * Time: 0MS
    * Memory: 137KB
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #define Max(a,b) (a>b?a:b)
    using namespace std;
    typedef long long(LL);
    typedef unsigned long long(ULL);
    const double eps(1e-8);

    const int MAXN=1000010;
    long long z[MAXN],f[MAXN],zz[MAXN],ff[MAXN];
    int a[MAXN];
    void scan(int &x)
    {
         x=0;
         char c=getchar();
         while(!(c>='0' && c<='9'  || c=='-')) { c=getchar(); }
         bool flag=1;
         if(c=='-')
         {
               flag=0; c=getchar();
         }
         while(c>='0' && c<='9')
         {
               x=x*10+c-'0'; c=getchar();
         }
         if(!flag) { x=-x; }
    }
    void scan2(int &x,int &y) { scan(x),scan(y);}
    void scan3(int &x,int &y,int &z) { scan(x),scan(y),scan(z); }

    void print(int x)
    {
         if(x>9) print(x/10);
         putchar(x%10+'0');
    }
    /**************************************END     define***************************************/
    int main()
    {
         int t;
         scanf("%d",&t);
         while(t--)
         {
               int n;
               scan(n);
               for(int i=0;i<n;++i) scan(a[i]);
               long long sum=0,ans1=0,ans2=0,mx;
               for(int i=0;i<n;++i)
               {
                     sum+=a[i];
                     if(sum<0) sum=0;
                     ans1=Max(ans1,sum);
               }
               z[0]=a[0],f[n-1]=a[n-1];
               for(int i=1;i<n;++i)
                     z[i]=z[i-1]+a[i];
               zz[0]=Max(0LL,z[0]),ff[n-1]=Max(0LL,f[n-1]);
               mx=zz[0];
               for(int i=1;i<n;++i)
               {
                     mx=Max(z[i],mx);
                     zz[i]=mx;
               }
               for(int i=n-2;i>=0;--i)
                     f[i]=f[i+1]+a[i];
               mx=ff[n-1];
               for(int i=n-2;i>=0;--i)
               {
                     mx=Max(f[i],mx);
                     ff[i]=mx;
               }
               for(int i=0;i<n-1;++i)
               {
                     ans2=Max(ans2,zz[i]+ff[i+1]);
               }
               printf("%I64d ",Max(ans1,ans2));
         }
         return 0;
    }
    /*

    */
  • 相关阅读:
    B轮公司技术问题列表(转)
    mysql函数之截取字符串
    谁才是真正的水果之王
    Mysql几种索引方式的区别及适用情况 (转)
    web安全之攻击
    css学习之样式层级和权重
    mysql中engine=innodb和engine=myisam的区别(转)
    mysql 创建表格 AUTO_INCREMENT
    mysql数据表的字段操作
    navicate使用小技巧
  • 原文地址:https://www.cnblogs.com/crazyacking/p/3644515.html
Copyright © 2011-2022 走看看