题目传送门
题意
给一个原序列,有两种操作,第一种,单点修改:把原来下标为A的数修改为B,第二种:给出区间A到B中,最大连续子段和。
思路
这个题我们需要去维护四个东西,1、区间和,2、最大前缀和 3、最大后缀和 4、最大连续子段和
那么,pushup函数的写法如下
void pushup(int p)
{
t[p].sum=t[ls].sum+t[rs].sum;
t[p].x=max(t[ls].mar+t[rs].mal,max(t[ls].x,t[rs].x));
t[p].mal=max(t[ls].sum+t[rs].mal,t[ls].mal);
t[p].mar=max(t[rs].sum+t[ls].mar,t[rs].mar);
return ;
}
总代码
//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=5e4+5;
const int mod=1e9+7;
const int INF=0x7fffffff;
//const ll LLINF=0x7fffffffffffffff;
const double EPS=1e-10;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define debug cout<<"debug"<<endl;
#define ls p<<1
#define rs p<<1|1
//#define int long long
int a[N];
struct tree
{
int l,r;
int mal,mar,x,sum;
tree()
{
mal=mar=x=sum=0;
}
}t[N<<2];
void pushup(int p)
{
t[p].sum=t[ls].sum+t[rs].sum;
t[p].x=max(t[ls].mar+t[rs].mal,max(t[ls].x,t[rs].x));
t[p].mal=max(t[ls].sum+t[rs].mal,t[ls].mal);
t[p].mar=max(t[rs].sum+t[ls].mar,t[rs].mar);
return ;
}
void build(int p,int x,int y)
{
t[p].l=x;t[p].r=y;
if(x==y)
{
t[p].sum=t[p].mal=t[p].mar=t[p].x=a[x];
return ;
}
int mid=x+y>>1;
build(ls,x,mid);
build(rs,mid+1,y);
pushup(p);
return ;
}
void change(int p,int x,int y)
{
if(t[p].l==x&&t[p].r==x)
{
t[p].sum=t[p].mal=t[p].mar=t[p].x=y;
return ;
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid)
change(ls,x,y);
else
change(rs,x,y);
pushup(p);
return ;
}
tree ask(int p,int x,int y)
{
if(x==t[p].l&&t[p].r==y)
{
return t[p];
}
int mid=t[p].l+t[p].r>>1;
tree a,b;
if(y<=mid)
return ask(ls,x,y);
if(x>mid)
return ask(rs,x,y);
a=ask(ls,x,mid);
b=ask(rs,mid+1,y);
tree c;
c.sum=a.sum+b.sum;
c.x=max(a.mar+b.mal,max(a.x,b.x));
c.mal=max(a.mal,a.sum+b.mal);
c.mar=max(b.mar,a.mar+b.sum);
return c;
}
signed main()
{
IOS;
//freopen("","r",stdin);
//freopen("","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
}
build(1,1,n);
int m;
scanf("%d",&m);
while(m--)
{
int oo,x,y;
scanf("%d%d%d",&oo,&x,&y);
if(oo==0)
{
change(1,x,y);
}
else
{
printf("%d\n",ask(1,x,y).x);
}
}
}