【题解】CH4301 线段树

题目链接

#include<cstdio>
#include<algorithm>
using namespace std;
#define lc (o<<1)
#define rc (o<<1|1)
#define _rep(i,a,b) for(int i=(a);i<=(b);i++)
const int N=5e5+10;
const int INF=0x3fffffff;
struct tree{
    int l,r,sum,dat,lmax,rmax;
}tr[N<<2];
int num[N];
//区间和sum,区间最大连续子段和dat,
//紧靠左端的最大连续子段和lmax
//紧靠右端的最大连续子段和rmax 
int n,m,x,y,k;
inline void Init(tree &a,int val)
{
    a.sum=a.dat=a.lmax=a.rmax=val;
}
inline void push_up(int o)
{
    tr[o].sum=tr[lc].sum+tr[rc].sum;
    tr[o].lmax=max(tr[lc].lmax,tr[lc].sum+tr[rc].lmax);
    tr[o].rmax=max(tr[rc].rmax,tr[rc].sum+tr[lc].rmax);
    tr[o].dat=max(max(tr[lc].dat,tr[rc].dat),tr[lc].rmax+tr[rc].lmax);
}
inline void build(int o,int l,int r)
{
    tr[o].l=l;tr[o].r=r;
    int mid=l+r>>1;
    Init(tr[o],num[l]);
    if(l==r)return;
    build(lc,l,mid);build(rc,mid+1,r);
    push_up(o);
}
inline void update(int o)
{
    if(tr[o].l==tr[o].r){Init(tr[o],y);return;}
    int mid=tr[o].l+tr[o].r>>1;
    if(x<=mid)update(lc);
    else update(rc);
    push_up(o);
}
inline tree query(int o)
{
    if(x<=tr[o].l&&tr[o].r<=y)return tr[o];
    tree a,b,c;
    int mid=tr[o].l+tr[o].r>>1;
    Init(a,-INF);Init(b,-INF);
    c.sum=0;
    if(x<=mid)a=query(lc),c.sum+=a.sum;
    if(y>mid)b=query(rc),c.sum+=b.sum;
    c.dat=max(max(a.dat,b.dat),a.rmax+b.lmax);
    c.lmax=max(a.lmax,b.lmax+a.sum);
    if(x>mid)c.lmax=max(c.lmax,b.lmax);
    c.rmax=max(b.rmax,b.sum+a.rmax);
    if(y<=mid)c.rmax=max(c.rmax,a.rmax);
    return c;
}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    _rep(i,1,n)scanf("%d",&num[i]);
    build(1,1,n);
    _rep(i,1,m)
    {
        scanf("%d%d%d",&k,&x,&y);
        if(k&1)
        {
            if(x>y)swap(x,y);
            printf("%d\n",query(1).dat);
        }
        else update(1);
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41958841/article/details/82313312