Can you answer these queries III(luogu)
Description
维护一个长度为n的序列A,进行q次询问或操作
0 x y:把Ax改为y
1 x y:询问区间【l,r】的最大子段和
数据范围:n,q<=5e4,-1e4<=Ai<=1e4;
Solution
线段树处理区间最大子段和
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define ll long long
using namespace std;
const int N=5e4+10;
struct node
{
ll sum,res,prel,prer;
int l,r,lc,rc;
}f[N*2],t;
int opt,tot,rt,n,q,x,y;
ll d[N];
void push_up(int g)
{
int lc=f[g].lc,rc=f[g].rc;
if(!lc) return ;
f[g].sum=f[lc].sum+f[rc].sum;
f[g].prel=max(f[lc].prel,f[lc].sum+f[rc].prel);
f[g].prer=max(f[rc].prer,f[rc].sum+f[lc].prer);
f[g].res=max(max(f[lc].res,f[rc].res),f[lc].prer+f[rc].prel);
}
void build(int &g,int l,int r)
{
g=++tot;
f[g].l=l,f[g].r=r;
if(l==r)
{
f[g].sum=f[g].prel=f[g].prer=f[g].res=d[l];
return ;
}
int mid=(l+r)>>1;
build(f[g].lc,l,mid),build(f[g].rc,mid+1,r);
push_up(g);
}
void change(int g,int x,int y)
{
if(f[g].l==f[g].r)
f[g].sum=f[g].res=f[g].prel=f[g].prer=y;
else
{
int mid=(f[g].l+f[g].r)>>1;
if(x<=mid) change(f[g].lc,x,y);
else change(f[g].rc,x,y);
push_up(g);
}
}
ll get(int g,int l,int r,node &a)
{
if(f[g].l==l && f[g].r==r)
{
a=f[g];
return a.res;
}
else
{
int mid=(f[g].l+f[g].r)>>1;
if(r<=mid) return get(f[g].lc,l,r,a);
else if(l>mid) return get(f[g].rc,l,r,a);
else
{
node b,c;
get(f[g].lc,l,mid,b);
get(f[g].rc,mid+1,r,c);
a.sum=b.sum+c.sum;
a.prel=max(b.prel,b.sum+c.prel);
a.prer=max(c.prer,c.sum+b.prer);
a.res=max(max(b.res,c.res),b.prer+c.prel);
return a.res;
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&d[i]);
build(rt,1,n);
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d",&opt,&x,&y);
if(!opt) change(rt,x,y);
else printf("%lld\n",get(rt,x,y,t));
}
return 0;
}
维护一个长度为 n 的序列 A,进行 m 次询问或操作:
0 x y
:将 Ax? 单调修改为 y1 x y
:求出 max{∑k=ij?Ak?}(x≤i≤j≤y)。数据范围:N,M≤5×104,∣Ai?∣≤104
Can you answer these queries III(线段树)
原文:https://www.cnblogs.com/hsez-cyx/p/12244948.html