给一个环,让你求环上最大连续子序列的和
一般是动态规划的思想,可是注意这个道题节点和操作都非常大, 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;
}