疯狂线段树90pts求调

P1253 扶苏的问题

sansesantongshun @ 2024-04-13 13:02:59

#include<bits/stdc++.h>
using namespace std;
int n,m,a[1000005],k,x,y,z;
long long b[4000005],c[4000005][2];
void build(int x,int l,int r)
{
    if (l==r)
    b[x]=a[l];
    else
    {
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        b[x]=max(b[x<<1],b[x<<1|1]);
    }
    c[x][0]=0x7fffffffffffffff;
}
void cover(int x)
{
    if (c[x][0]!=0x7fffffffffffffff)
    {
        b[x<<1]=c[x][0];
        b[x<<1|1]=c[x][0];
        c[x<<1][0]=c[x][0];
        c[x<<1|1][0]=c[x][0];
        c[x<<1][1]=0;
        c[x<<1|1][1]=0;
        c[x][0]=0x7fffffffffffffff;
    }
}
void pushdown(int x,int l,int r)
{
    cover(x);
    if (c[x][1])
    {
        int mid=l+r>>1;
        cover(x);
        b[x<<1]+=c[x][1];
        b[x<<1|1]+=c[x][1];
        c[x<<1][1]+=c[x][1];
        c[x<<1|1][1]+=c[x][1];
        c[x][1]=0;
    }
}
void modify1(int x,int bl,int br,int l,int r,int y)
{
    if (l<=bl && br<=r)
    {
        b[x]=y;
        c[x][0]=y;
        c[x][1]=0;
    }
    else
    {
        int mid=bl+br>>1;
        pushdown(x,bl,br);
        if (l<=mid)
        modify1(x<<1,bl,mid,l,r,y);
        if (mid<r)
        modify1(x<<1|1,mid+1,br,l,r,y);
        b[x]=max(b[x<<1],b[x<<1|1]);
    }
}
void modify2(int x,int bl,int br,int l,int r,int y)
{
    if (l<=bl && br<=r)
    {
        cover(x);
        b[x]+=y;
        c[x][1]+=y;
    }
    else
    {
        int mid=bl+br>>1;
        pushdown(x,bl,br);
        if (l<=mid)
        modify2(x<<1,bl,mid,l,r,y);
        if (mid<r)
        modify2(x<<1|1,mid+1,br,l,r,y);
        b[x]=max(b[x<<1],b[x<<1|1]);
    }
}
long long query(int x,int bl,int br,int l,int r)
{
    if (l<=bl && br<=r)
    return b[x];
    int mid=bl+br>>1;
    long long result=-0x8000000000000000;
    pushdown(x,bl,br);
    if (l<=mid)
    result=max(result,query(x<<1,bl,mid,l,r));
    if (mid<r)
    result=max(result,query(x<<1|1,mid+1,br,l,r));
    return result;
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;++i)
    scanf("%d",&a[i]);
    build(1,1,n);
    while (m--)
    {
        scanf("%d",&k);
        if (k==1)
        {
            scanf("%d%d%d",&x,&y,&z);
            modify1(1,1,n,x,y,z);
        }
        else if (k==2)
        {
            scanf("%d%d%d",&x,&y,&z);
            modify2(1,1,n,x,y,z);
        }
        else
        {
            scanf("%d%d",&x,&y);
            cout<<query(1,1,n,x,y)<<'\n';
        }
    }
}

by ilibilib @ 2024-04-13 13:57:46

@sansesantongshun 数组开小了好像 https://www.luogu.com.cn/record/155635065


by sansesantongshun @ 2024-04-13 16:37:30

@ilibilib A了,但为啥小了啊,不是 10^6


by ilibilib @ 2024-04-13 16:49:53

@sansesantongshun

\log_2 1000000 \approx 19.931

线段树数组好像要开 4*(1<<20) 的样子


by lhp964515118 @ 2024-04-30 11:01:40

发现原因了,的确线段树开4倍就行,这道题1e6的数据4e6+5的空间不行的原因是因为没有考虑push_down时,当前节点是不是叶子节点,因为增加操作时,需要先下传覆盖标记,这个时候如果是叶子,也会下传,那么需要的空间就会更大,加一个判断,是叶子就不用下传,空间4e6+5就足够了


by sansesantongshun @ 2024-05-06 21:44:09

@lhp964515118 但是叶子结点一定直接返回不会下传


by lhp964515118 @ 2024-05-08 11:22:01

@sansesantongshun 在增加区间值的时候,需要先判断这个区间是否被修改为固定值了,这个时候,如果该区间是叶子节点,那也会去判断是否被修改为固定值,也就是你的modify2中,还是会调用cover函数,那这个时候,cover就会越界


by lhp964515118 @ 2024-05-08 11:23:00

@lhp964515118 加一个if判断l<r时再cover就行了


|