zoukankan      html  css  js  c++  java
  • 线段树区间覆盖和区间累加的区别

    区间覆盖:

    题目链接:https://vjudge.net/contest/269834#problem/D

    AC代码:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<stack>
    #include<map>
    #include<stdio.h>
    #include<queue>
    #include<algorithm>
    using namespace std;
    # define inf 0x3f3f3f3f
    # define ll long long
    # define maxn 5000000+1000
    # define lson l,m,rt<<1
    # define rson m+1,r,rt<<1|1
    ll a[maxn];
    int col[maxn];
    int n,m;
    void up(int rt)
    {
        a[rt]=a[rt<<1]+a[rt<<1|1];
    }
    void down(int rt,int l,int r)
    {
        if(col[rt]!=-1)
        {
            col[rt<<1]=col[rt<<1|1]=col[rt];
            int mid=(l+r)>>1;
            a[rt<<1]=col[rt]*(mid-l+1);//注意这里长度的赋值
            a[rt<<1|1]=col[rt]*(r-mid);
            col[rt]=-1;
        }
    }
    void buildtree(int l,int r,int rt)
    {
        col[rt]=-1;
        if(l==r)
        {
            a[rt]=1;
            return ;
        }
        int m=(l+r)>>1;
        buildtree(lson);
        buildtree(rson);
        up(rt);
    }
    void update(int L,int R,int p,int l,int r,int rt)
    {
        if(L<=l&&R>=r)
        {
            a[rt]=p*(r-l+1);
            col[rt]=p;
            return ;
        }
        down(rt,l,r);
        int m=(l+r)>>1;
        if(L<=m)update(L,R,p,lson);
        if(R>m)update(L,R,p,rson);
        up(rt);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        int num=0;
        while(T--)
        {
            scanf("%d",&n);
            buildtree(1,n,1);
            int t1,t2,t3;
            scanf("%d",&m);
            while(m--)
            {
                scanf("%d%d%d",&t1,&t2,&t3);
                update(t1,t2,t3,1,n,1);
            }
            printf("Case %d: The total value of the hook is %lld.
    ",++num,a[1]);
        }
        return 0;
    }
    

    区间累加:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<stack>
    #include<map>
    #include<stdio.h>
    #include<queue>
    #include<algorithm>
    using namespace std;
    # define inf 0x3f3f3f3f
    # define ll long long
    # define maxn 50000000+1000
    # define lson l,m,rt<<1
    # define rson m+1,r,rt<<1|1
    ll a[maxn];
    ll col[maxn];
    ll n,m;
    void up(ll rt)
    {
        a[rt]=a[rt<<1]+a[rt<<1|1];
    }
    void down(ll rt,ll len)
    {
        if(col[rt]!=0)
        {
            col[rt<<1]+=col[rt];
            col[rt<<1|1]+=col[rt];
            a[rt<<1]+=col[rt]*(len-len/2);
            a[rt<<1|1]+=col[rt]*(len/2);
            col[rt]=0;
        }
    }
    void buildtree(ll l,ll r,ll rt)
    {
        col[rt]=0;
        if(l==r)
        {
            scanf("%lld",&a[rt]);
            return ;
        }
        ll m=(l+r)>>1;
        buildtree(lson);
        buildtree(rson);
        up(rt);
    }
    void update(ll L,ll R,ll p,ll l,ll r,ll rt)
    {
        if(L<=l&&R>=r)
        {
            a[rt]+=p*(r-l+1);
            col[rt]+=p;
            return ;
        }
        down(rt,r-l+1);
        ll m=(l+r)>>1;
        if(L<=m)update(L,R,p,lson);
        if(R>m)update(L,R,p,rson);
        up(rt);
    }
    ll query(ll L,ll R,ll l,ll r,ll rt)
    {
        if(L<=l&&R>=r)
        {
            return a[rt];
        }
        ll m=(l+r)>>1;
        ll ans=0;
        down(rt,r-l+1);
        if(L<=m)ans+=query(L,R,lson);
        if(R>m)ans+=query(L,R,rson);
        return ans;
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        buildtree(1,n,1);
        ll t1,t2,t3;
        char str[10];
        while(m--)
        {
            scanf("%s",str);
            if(str[0]=='C')
            {
                scanf("%lld%lld%lld",&t1,&t2,&t3);
                update(t1,t2,t3,1,n,1);
            }
            else if(str[0]=='Q')
            {
                scanf("%lld%lld",&t1,&t2);
                printf("%lld
    ",query(t1,t2,1,n,1));
            }
        }
        return 0;
    }
    

    反思:

    通过观察上面的两个样例,可以感觉到线段树只有这里不太一样。

    1/--------------------------------------------------
     if(L<=l&&R>=r)
        {
            a[rt]+=p*(r-l+1);
            col[rt]+=p;
            return ;
        }
    
    
    
    void down(ll rt,ll len)
    {
        if(col[rt]!=0)
        {
            col[rt<<1]+=col[rt];
            col[rt<<1|1]+=col[rt];
            a[rt<<1]+=col[rt]*(len-len/2);
            a[rt<<1|1]+=col[rt]*(len/2);
            col[rt]=0;
        }
    }
    /-----------------------------------------------------
    
    
    2
    /----------------------------------------------------
    if(L<=l&&R>=r)
        {
            a[rt]=p*(r-l+1);
            col[rt]=p;
            return ;
        }
    
       if(col[rt]!=-1)
        {
            col[rt<<1]=col[rt<<1|1]=col[rt];
            int mid=(l+r)>>1;
            a[rt<<1]=col[rt]*(mid-l+1);
            a[rt<<1|1]=col[rt]*(r-mid);
            col[rt]=-1;
        }
    /------------------------------------------------------

    观看这两个线段树的区别,第一个是用来累加的,第二个是用来覆盖的。

    对于第一个来说,每一个父节点存储的是当前这个点以及当前这个点往下的权值,而对于第二个来说,存储的是当前这个点的颜色,每一次操作并不会收到以前的影响,所以直接覆盖掉就可以了,但是第一个如果覆盖掉的话,以前的权值就会消失,这就是这两个题的不同。

  • 相关阅读:
    CCCC 2020 酱油记
    CCPC 2020 威海 滚粗记
    IEEExtreme 2020 酱油记
    CCSP 2020 酱油记
    ICPC 陕西省赛 2020 游记
    CCPC 网络赛 2020 自闭记
    CSP 第20次认证 酱油记
    CSP-S 2019 酱油记
    NOI2019 退役记
    树链剖分入门
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262819.html
Copyright © 2011-2022 走看看