POJ 2750

给一个环,让你求环上最大连续子序列的和

一般是动态规划的思想,可是注意这个道题节点和操作都非常大, DP肯定行不通, 由于它要经常更新节点, 我们想到了动态规划, 想了一个小时,。。。没什么正确的思路,看了大牛的思想。。只能说太神奇了


  L ~ R最大连续序列值 只可能是两种情况, (1)同时包含 L R,  (2)不同时 不包含L,R

  

具体怎么求法呢?

假设我们将整个序列分成两个连续的序列a,b;与整个序列设成A。假如我们知道a,b序列各个的从左向右最大连续序列值lmax,从右往左的最大连续序列值rmax,和从左向右最小连续序列值lmin,从右往左的最小连续序列值rmin,和每个序列的最大连续序列值nmax和最小连续序列值nmin,和最大元素值max,和最小元素值min;

那么,就有:

A.nmax=max(a.nmax,b.max,a.rmax+b.lmax,);

A.lmax=max(a.sum+b.lmax,a.max);

A.rmax=max(b.sum+a.rmax,b.rmax);

A.lmin=min(a.sum+b.lmin,a.lmin);

A.rmin=min(b.sum+a.rmin,b.rmin);

A.min=min(a.min,b.min) ;

A.max=max(a.max,b.max) ;

现在的A.nmax并不是最终结果,因为还没考虑最大连续序列值存在两端的情况,

A.nmax=max(A.nmax,A.sum-(a.rmin+b.lmin))

这是不是最终的答案呢? 不是,因为没有考虑全为正数和全为负数的情况,所以这种情况下

A.nmax=A.namx-A.min 或 A.nmax=A.max ;

 

有两种写法 一种是结构体, 必较好理解, 另一种是数组


结构体

 

#include <iostream>
#include <string.h>
#include <stdio.h>


using namespace std;


#define MAXN 111111
#define max(a, b) (a) > (b) ? (a) :(b)
#define min(a, b) (a) < (b) ? (a) :(b)
struct node
{
    int sum, intmax, intmin;
    int lmax, lmin, rmax, rmin;
}vec[MAXN<< 2];


void pushup(int rt)
{
    vec[rt].sum = vec[rt << 1].sum + vec[rt << 1|1].sum;


    vec[rt].lmax = max(vec[rt<<1].lmax, vec[rt<<1].sum + vec[rt<<1|1].lmax);
    vec[rt].lmin = min(vec[rt<<1].lmin, vec[rt<<1].sum + vec[rt<<1|1].lmin);


    vec[rt].rmax = max(vec[rt<<1|1].rmax, vec[rt<<1|1].sum + vec[rt<<1].rmax);
    vec[rt].rmin = min(vec[rt<<1|1].rmin, vec[rt<<1|1].sum + vec[rt<<1].rmin);




    vec[rt].intmax = max(vec[rt<<1].intmax, vec[rt<<1|1].intmax);
    vec[rt].intmax = max(vec[rt].intmax, vec[rt<<1].rmax + vec[rt<<1|1].lmax);


    vec[rt].intmin = min(vec[rt<<1].intmin, vec[rt<<1|1].intmin);
    vec[rt].intmin = min(vec[rt].intmin, vec[rt<<1].rmin + vec[rt<<1|1].lmin);
}


void init( int rt, int num)
{
    vec[rt].intmax = vec[rt].intmin = num;
    vec[rt].lmax = vec[rt].lmin = num;
    vec[rt].rmax = vec[rt].rmin = num;
    vec[rt].sum = num;
}




void build( int l, int r, int rt)
{
    if(l == r)
    {
        scanf("%d",&vec[rt].sum);
        init(rt, vec[rt].sum);
        return ;
    }
    int m = (l + r) >>1 ;
    build( l, m, rt<<1);
    build( m + 1, r, rt<<1|1);
    pushup(rt);


}




void update(int p, int val, int l, int r, int rt)
{
    if(l == r)
    {
        init(rt,val);
        return ;
    }
    int m = ( l + r) >> 1;
    if(p <= m) update( p, val, l, m, rt << 1);
     else update(p, val, m+1, r, rt<<1|1);
    pushup(rt);
}


int output( )
{
    if(vec[1].intmax < vec[1].sum - vec[1].intmin)
      vec[1].intmax = vec[1].sum - vec[1].intmin;


    if(vec[1].sum == vec[1].intmax)
      vec[1].intmax = vec[1].sum - vec[1].intmin;


    if(vec[1].sum == vec[1].intmin)
      vec[1].intmax = vec[1].sum - vec[1].intmin;


  return vec[1].intmax;


}


int main()
{
   int n, m, k, x;
   while(scanf("%d",&n)!= EOF)
   {
       build(1, n, 1);
       scanf("%d",&m);
       for( int i = 0; i < m; i++)
       {
           scanf("%d %d",&x, &k);
           update(x, k, 1, n, 1);
           printf("%d\n",output());
       }


   }
   return 0;
}




#include <iostream>
#include <string.h>
#include <stdio.h>


using namespace std;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define max(a, b) (a) > (b) ? (a):(b)
#define min(a, b) (a) < (b) ? (a):(b)
#define MAXN 111111
int sum[MAXN << 2];
int lmax[MAXN << 2], lmin[MAXN << 2];
int rmax[MAXN << 2], rmin[MAXN << 2];
int intmax[MAXN << 2], intmin[MAXN << 2];




void pushup( int rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];


    rmax[rt] = max(rmax[rt<<1|1], rmax[rt<<1] + sum[rt<<1|1]);
    lmax[rt] = max(lmax[rt<<1], sum[rt<<1] + lmax[rt<<1|1]);


    rmin[rt] = min(rmin[rt<<1|1], sum[rt<<1|1] + rmin[rt<<1]);
    lmin[rt] = min(lmin[rt<<1], sum[rt<<1] + lmin[rt<<1|1]);


    intmax[rt] = max(intmax[rt<<1],intmax[rt<<1|1] );
    intmax[rt] = max(intmax[rt], rmax[rt<<1]+ lmax[rt<<1|1]);


    intmin[rt] = min(intmin[rt<<1], intmin[rt<<1|1]);
    intmin[rt] = min(intmin[rt], rmin[rt<<1] + lmin[rt<<1|1]);
}


void build( int l, int r, int rt)
{
    if( l == r)
    {
        scanf("%d",&sum[rt]);
        lmax[rt] = lmin[rt] = sum[rt];
        rmax[rt] = rmin[rt] = sum[rt];
        intmax[rt] = intmin[rt] = sum[rt];


        return ;
    }
    int m = ( l + r) >> 1;
    build(lson);
    build(rson);
    pushup(rt);
}


void update( int p, int val, int l, int r, int rt)
{
    if(l == r)
    {
        sum[rt] = intmin[rt] = intmax[rt] = val;
        lmax[rt] = rmax[rt] = lmin[rt] = rmin[rt] = val;
        return ;
    }
    int m = ( l + r) >> 1;
    if(p <= m) update(p, val, lson);
    else update(p, val, rson);
    pushup(rt);
}


int output( )
{


    int ans;
    if (sum[1] == intmax[1]) //序列全为非负数的时候


        ans = sum[1] - intmin[1];


    else ans = max(intmax[1], sum[1]-intmin[1]);




    return ans;
}
int main()
{
    int n, k, m, x;
    while(scanf("%d",&n)!= EOF)
    {
        build(1, n, 1);
        scanf("%d",&m);
        for( int i = 0; i < m; i++)
        {
            scanf("%d %d",&x, &k);
            update(x, k, 1, n, 1);
            printf("%d\n",output());
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值