A Simple Problem with Integers POJ - 3468

本文深入讲解了线段树数据结构的实现与应用,包括区间修改和区间查询等核心操作,并通过一个具体示例展示了如何利用懒惰标记提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击打开链接

最近刚接触线段树 感觉很神奇

这道题是区间修改区间查询 pre[n*4]数组是关键(此题可以和懒惰标记合并)

只要pre[cur]不为零 就说明有上一次未完成的更新 这里的pre[cur]应该是“+=”而不是“=”

因为可能存在这种情况 上一次你在该点打了懒惰标记 但是还未及更新其子节点 这一次的更新又来到此点 此时用“=”会将上一次的覆盖 WA了好几次。。

 

#include <stdio.h>

long long sum[400001],pre[400001];
int laz[400001];
int n;

void pushup(int cur);
void pushdown(int len,int cur);
void build(int l,int r,int cur);
void update(int ll,int rr,long long val,int l,int r,int cur);
long long query(int ll,int rr,int l,int r,int cur);

int main()
{
    long long c;
    int q,i,a,b;
    char ch[2];
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        for(i=1;i<=n*4;i++)
        {
            sum[i]=0;
            pre[i]=0;
            laz[i]=0;
        }
        build(1,n,1);
        while(q--)
        {
            scanf("%s",ch);
            if(ch[0]=='C')
            {
                scanf("%d%d%lld",&a,&b,&c);
                update(a,b,c,1,n,1);
            }
            else
            {
                scanf("%d%d",&a,&b);
                printf("%lld\n",query(a,b,1,n,1));
            }
        }
    }
    return 0;
}

void pushup(int cur)
{
    sum[cur]=sum[cur*2]+sum[cur*2+1];
    return;
}

void pushdown(int len,int cur)
{
    if(laz[cur]==1)
    {
        sum[cur*2]+=pre[cur]*(len-len/2);
        pre[cur*2]+=pre[cur];
        laz[cur*2]=1;
        sum[cur*2+1]+=pre[cur]*(len/2);
        pre[cur*2+1]+=pre[cur];
        laz[cur*2+1]=1;
        pre[cur]=0;
        laz[cur]=0;
    }
    return;
}

void build(int l,int r,int cur)
{
    int m;
    if(l==r)
    {
        scanf("%lld",&sum[cur]);
        return;
    }
    m=(l+r)/2;
    build(l,m,cur*2);
    build(m+1,r,cur*2+1);
    pushup(cur);
    return;
}

void update(int ll,int rr,long long val,int l,int r,int cur)
{
    int m;
    if(ll<=l&&r<=rr)
    {
        sum[cur]+=(r-l+1)*val;
        pre[cur]+=val;
        laz[cur]=1;
        return;
    }
    pushdown(r-l+1,cur);
    m=(l+r)/2;
    if(ll<=m) update(ll,rr,val,l,m,cur*2);
    if(rr>m) update(ll,rr,val,m+1,r,cur*2+1);
    pushup(cur);
    return;
}

long long query(int ll,int rr,int l,int r,int cur)
{
    long long ans;
    int m;
    if(ll<=l&&r<=rr)
    {
        return sum[cur];
    }
    pushdown(r-l+1,cur);
    ans=0,m=(l+r)/2;
    if(ll<=m) ans+=query(ll,rr,l,m,cur*2);
    if(rr>m) ans+=query(ll,rr,m+1,r,cur*2+1);
    return ans;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值