线段树进阶。
传送门:点击打开链接
题目大意:
给一个序列。有两种操作。
1>: 区间查询:查询(l,r)之间的最大连续字段和。
2>: 单点修改。
解题思路:
用线段树维护pre_sum,suf_sum,sum。
那么这个区间的pre_sum = 左区间的pre_sum,(左区间的sum+右区间的pre_sum)的最大值。
suf同理。
#include<cstdio>
#include <cstdint>
#define maxn 500010
struct Node
{
int l,r,pre_sum,suf_sum,sum;
int ans;
}tree[maxn<<2];
int v[maxn];
inline int max(int a,int b)
{
return a>b?a:b;
}
inline void pushup(int id)
{
tree[id].pre_sum = max(tree[id<<1].pre_sum,tree[id<<1].sum+tree[id<<1|1].pre_sum);
tree[id].suf_sum = max(tree[id<<1|1].suf_sum,tree[id<<1|1].sum+tree[id<<1].suf_sum);
tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
tree[id].ans = max(max(tree[id<<1].ans,tree[id<<1|1].ans),tree[id<<1].suf_sum+tree[id<<1|1].pre_sum);
}
void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
if(l == r)
{
tree[id].sum = tree[id].pre_sum = tree[id].suf_sum = tree[id].ans = v[l];
}
else
{
int mid = (l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}
}
void update(int id,int pos,int x)
{
if(tree[id].l == tree[id].r)
{
tree[id].sum = tree[id].pre_sum = tree[id].suf_sum = tree[id].ans = x;
}
else
{
int mid = (tree[id].l+tree[id].r)>>1;
if(pos <= mid) update(id<<1,pos,x);
else update(id<<1|1,pos,x);
pushup(id);
}
}
void query(int id,int l,int r,int &sum,int &pre_sum,int &suf_sum,int &ans)
{
if(l <= tree[id].l && tree[id].r <= r)
{
sum = tree[id].sum;
pre_sum = tree[id].pre_sum;
suf_sum = tree[id].suf_sum;
ans = tree[id].ans;
}
else
{
int mid = (tree[id].l+tree[id].r)>>1;
int sum1,pre1,suf1,ans1,sum2,pre2,suf2,ans2;
if(r <= mid)
{
query(id<<1,l,r,sum,pre_sum,suf_sum,ans);
}
else if(l > mid)
{
query(id<<1|1,l,r,sum,pre_sum,suf_sum,ans);
}
else
{
query(id<<1,l,r,sum1,pre1,suf1,ans1);
query(id<<1|1,l,r,sum2,pre2,suf2,ans2);
sum = sum1+sum2;
pre_sum = max(pre1,sum1+pre2);
suf_sum = max(suf2,sum2+suf1);
ans = max(max(ans1,ans2),pre2+suf1);
}
}
}
int main()
{
int n,q;
while(~scanf("%d %d",&n,&q))
{
for(int i = 1;i <= n;i++) scanf("%d",&v[i]);
build(1,1,n);
while(q--)
{
int id;
scanf("%d",&id);
if(id ==1)
{
int l,r;
scanf("%d %d",&l,&r);
int sum,pre_sum,suf_sum,ans;
query(1,l,r,sum,pre_sum,suf_sum,ans);
printf("%d\n",ans);
}
else
{
int pos,x;
scanf("%d %d",&pos,&x);
update(1,pos,x);
}
}
}
return 0;
}