求助,线段树,search数组有问题

P3372 【模板】线段树 1

GLESENA @ 2023-08-03 19:40:52

代码 :

#include<bits/stdc++.h>
using namespace std;
#define lc i<<1
#define rc i<<1|1
#define mid (l+r)/2
int inPut[100000+1];
struct tree{
    int l,r,sum,lazytag;
}t[100000001];
void push_down(int i)
{
    t[lc].lazytag+=t[i].lazytag;
    t[rc].lazytag+=t[i].lazytag;
    t[lc].sum+=t[i].lazytag*(t[lc].r-t[lc].l+1);
    t[rc].sum+=t[i].lazytag*(t[rc].r-t[rc].l+1);
    t[i].lazytag=0;
}
void build(int i,int l,int r)
{
    t[i].l=l;t[i].r=r;
    if(l==r)
    {
        t[i].sum=inPut[l];
        return ;
    }
    build(lc,l,mid);
    build(rc,mid+1,r);
    t[i].sum=t[lc].sum+t[rc].sum;
}
int search(int i,int l,int r)
{
    //cout<<t[i].l<<" "<<t[i].r<<' '<<l<<' '<<r<<'\n';
    if(l<=t[i].l&&r>=t[i].r)
    {
        return t[i].sum+t[i].lazytag*(t[i].r-t[i].l+1);
    }
    if(l>=t[i].r||r<=t[i].l)
    {
        return 0;
    }
    int rtrn=0;
    push_down(i);
    if(l<=t[lc].r)
    {
        rtrn+=search(lc,l,r);
    }
    if(r>=t[rc].l)
    {
        rtrn+=search(rc,l,r);
    }
    return rtrn;
}
void add(int i,int l,int r,int k)
{
    if(l<=t[i].l&&r>=t[i].r)
    {
        t[i].lazytag=k;
        t[i].sum+=k*(t[i].r-t[i].l+1);
        return ;
    }
    push_down(i);
    if(l<=t[lc].r)
    {
        add(lc,l,r,k);
    }
    if(r>=t[rc].l)
    {
        add(rc,l,r,k);
    }
    t[i].sum=t[lc].sum+t[rc].sum;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&inPut[i]);
    }
    build(1,1,n);
    int op,x,y,k;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%d",&x,&y,&k);
            add(1,x,y,k);
        }
        if(op==2)
        {
            scanf("%d%d",&x,&y);
            cout<<search(1,x,y)<<endl;
        }
    }
    return 0;
}

求区间和时,位于区间边缘的数如果需要push_back到t[i].l==t[i].r,就无法被计算。

如 输入

8 1
1 1 1 1 1 1 1 1
2 4 6

输出

2

如下面横线下的3个1都应该被计算,结果应该为1+1+1=3。 但第4个1没有被计算,只计算了第5和第6个1,结果为输出了2。

      _____
1 1 1 1 1 1 1 1
1 1 1 1|1 1 1 1
1 1|1 1|1 1|1 1
1|1|1|1|1|1|1|1
1 2 3 4 5 6 7 8 

也就是说,search函数正确无法查询到长度为1的区间的值。

蒟蒻求助。


by _Fancy_ @ 2023-08-03 19:43:16

@GLESENA search不得先求一个mid再比较吗


by _Fancy_ @ 2023-08-03 19:46:03

@yutiti80

int rtrn=0;
int mid=t[i].l+t[i].r>>1;
push_down(i);
if(l<=mid)
{
    rtrn+=search(lc,l,r);
}
if(r>=mid)
{
   rtrn+=search(rc,l,r);
}

by NightTide @ 2023-08-03 19:48:19

@GLESENA 第二个 if 吧等于号去掉


by NightTide @ 2023-08-03 19:48:53

@GLESENA 最后两个 if 是和 mid 比


|