求区间的最长子序列和
这道题我也不是很懂,不过模板在这里了
#include <iostream>
#include <algorithm>
#include <cstdio>
#define L o<<1
#define R o<<1|1
#define cmax(a,b) a>b?a:0
//求区间内子序列的最大和
//需要比较的是 连续左边一段 连续右边一段 整一段
using namespace std;
struct node
{
int l,r;
int mx,lx,rx,sum;
}m[200000];
int a[50009];
int ant;//这是求出的最大值
int pre;//记录求区间时的前一段
//所求出的lx,rx,mx区间子序列一定是连续的
void pushup(int o)
{
m[o].sum=m[L].sum+m[R].sum;
m[o].lx=max(m[L].lx,m[L].sum+m[R].lx);//是哪一个的max,这里就都是max
//例如.lx 这里面都是.lx
//左边和+右边最大
m[o].rx=max(m[R].rx,m[R].sum+m[L].rx);//左边最大+右边的和
m[o].mx=max(max(m[R].mx,m[L].mx),m[L].rx+m[R].lx);//左边最大+右边最大
}
void build(int o,int l,int r)
{
m[o].l=l;
m[o].r=r;
if(l==r)
{
m[o].sum=m[o].lx=m[o].rx=m[o].mx=a[l];//这里是l
return ;
}
int mid=(l+r)/2;
build(L,l,mid);
build(R,mid+1,r);
pushup(o);//求的都是m[o]
}
void query(int o,int l,int r)
{
if(l<=m[o].l&&m[o].r<=r)//当在区间时
{
ant=max(m[o].mx,ant);
ant=max(pre+m[o].lx,ant);
pre=max(pre+m[o].sum,m[o].rx);
return ;
}
int mid=(m[o].l+m[o].r)/2;
if(l<=mid) query(L,l,r);//这里是[l,r]区间
if(r>mid) query(R,l,r);
}
int main()
{
int n,m,c,b,i;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,1,n);
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&b,&c);
ant=a[b];
pre=0;
query(1,b,c);
printf("%d\n",ant);
}
}
对于要求区间最大子序列和,那么需要比较的是 左边连续子序列 右边连续子序列 整段连续子序列
利用ant返回最大值,先比较总的m[o].mx,然后再比较pre(之前它所取的最大一段)+m[o].lx(左边最大),最后再更新pre