zoukankan      html  css  js  c++  java
  • POJ3468A Simple Problem with Integers(线段树区间更新)

    https://vjudge.net/problem/POJ-3468

    线段树区间更新,记录模板

    #include<stdio.h>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxa=100005;
    ll c,s[maxa],lazy[maxa*4],sum[maxa*4];
    int n,q,a,b;
    char ch;
    
    void build(int l,int r,int rt)
    {
        int mid=(l+r)/2;
        if(l==r)
        {
            sum[rt]=s[mid];
            return ;
        }
        build(l,mid,rt*2);
        build(mid+1,r,rt*2+1);
        sum[rt]=sum[rt*2]+sum[rt*2+1];
    }
    
    void pushdown(int rt,int len)       ///rt为sum下标,后者是该区间的数组元素个数
    {
        if(lazy[rt])
        {
            lazy[rt*2]  += lazy[rt];
            lazy[rt*2+1]+= lazy[rt];    ///父节点有标记,把标记给两个儿子
            sum[rt*2]   += (ll)(len-len/2)*lazy[rt];
            sum[rt*2+1] += (ll)(len/2)*lazy[rt];
            lazy[rt]=0;                 ///消除标记,底层的没有办法消除,
        }
    }
    
    void update(int l,int r,int rt,ll c)
    {
        if(a<=l && r<=b)            ///如果区间在修改范围里,标记一下rt
        {
            lazy[rt]+=c;            ///如果没有消除,需要叠加,如果消除过,也是和0叠加
            sum[rt]+= (ll)c*(r-l+1);///直接加到大区间段,不要细分下去,节省时间
            return ;
        }
        pushdown(rt,r-l+1);///搞不好下面就需要用到标记区间的左右子树数据,所以都要先
        int mid = (l+r)/2;
        if(b<=mid)
            update(l,mid,rt*2,c);
        else if(a>mid)
            update(mid+1,r,rt*2+1,c);
        else
        {
            update(l,mid,rt*2,c);
            update(mid+1,r,rt*2+1,c);
        }
        sum[rt]=sum[rt*2]+sum[rt*2+1];
    }
    ll query(int l,int r,int rt)
    {
    
        if( a<=l && r<=b )   return sum[rt];
        pushdown(rt,r-l+1);
        int mid = (l+r)/2;
        if(b<=mid)
            return query(l,mid,rt*2);
        else if(a>mid)
            return query(mid+1,r,rt*2+1);
        else
        return query(l,mid,rt*2)+query(mid+1,r,rt*2+1);
    }
    
    int main()
    {
        memset(lazy,0,sizeof(lazy));
        memset(sum,0,sizeof(sum));
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
            scanf("%lld",&s[i]);
        build(1,n,1);
    
        while(q--)
        {
            getchar();///吸收回车键
            scanf("%c",&ch);
            if(ch=='Q')
            {
                scanf("%d%d",&a,&b);
    
                printf("%lld\n",query(1,n,1));
            }
            else
            {
                scanf("%d%d%lld",&a,&b,&c);
                update(1,n,1,c);
            }
        }
        return 0;
    }
     
  • 相关阅读:
    centos安装rvm报错@curl -L get.rvm.io | bash -s stable fails on cent OS
    linux命令 环境设置 顺序
    mysql-5.7.20基本用法
    gitlab&Jenkins 详细介绍及其应用
    git 详细部署及其应用
    zabbix详细介绍及其自动动态发现
    redis 缓存应用
    Linux下rpm、yum和源码三种安装方式详细介绍
    js中获取时间new date()的用法
    Apache Tomcat/8.5.56 启动命令行中文乱码
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/9441584.html
Copyright © 2011-2022 走看看