zoukankan      html  css  js  c++  java
  • 【codevs1082】线段树练习 3

    题目描述 Description

    给你N个数,有两种操作:

    1:给区间[a,b]的所有数增加X

    2:询问区间[a,b]的数的和。

    输入描述 Input Description

    第一行一个正整数n,接下来n行n个整数,

    再接下来一个正整数Q,每行表示操作的个数,

    如果第一个数是1,后接3个正整数,

    表示在区间[a,b]内每个数增加X,如果是2,

    表示操作2询问区间[a,b]的和是多少。

    pascal选手请不要使用readln读入

    输出描述 Output Description

    对于每个询问输出一行一个答案

    样例输入 Sample Input

    3

    1

    2

    3

    2

    1 2 3 2

    2 2 3

    样例输出 Sample Output

    9

    数据范围及提示 Data Size & Hint

    数据范围

    1<=n<=200000

    1<=q<=200000

    分析

    对于线段树的区间修改时,我们不可能一个一个地把区间内的每一个点都修改了。那样很耗时,而且有可能有很多点我们用不到。

    当要把一个区间的值增加一个数时,我们可以先更新这个区间的值,然后在给这个区间打上一个延迟标记表示下面的区间还未更新,因为下面的区间我们可能用不到。当要用到下面的区间时,就可以将延迟标记向下面传递,更新下面区间的值,用得到就更新,用不到就不更新,这就是延迟标记。

    总结一下,用延迟标记对区间修改时,被打上标记的区间的值是被更新过的,而下面的区间是未被更新的,因为有可能用不到所以不必更新,当用到下面的区间时就传递延迟标记,更新左右区间的值。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=200000+5;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int n,m,len;
    int a[maxn];
    struct node
    {
        int l,r,lc,rc,add;
        ll c;
    }tr[maxn<<1];
    inline void bt(int x,int y)
    {
        len++; int now=len;
        tr[now].l=x; tr[now].r=y;
        if(x==y) tr[now].c=a[x];
        else
        {
            int mid=(x+y)>>1;
            tr[now].lc=len+1; bt(x,mid);
            tr[now].rc=len+1; bt(mid+1,y);
            tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
        }
    }
    inline void pushdown(int now)
    {
        int lc=tr[now].lc,rc=tr[now].rc;
        tr[lc].c+=tr[now].add*(tr[lc].r-tr[lc].l+1);
        tr[rc].c+=tr[now].add*(tr[rc].r-tr[rc].l+1);
        tr[lc].add+=tr[now].add;
        tr[rc].add+=tr[now].add;
        tr[now].add=0;
    }
    inline void update(int now,int x,int y,int k)
    {
        if(tr[now].l==x&&tr[now].r==y)
        {
            tr[now].c+=k*(tr[now].r-tr[now].l+1);
            tr[now].add+=k;
        }else 
        {
            int lc=tr[now].lc,rc=tr[now].rc;
            pushdown(now);
            int mid=(tr[now].l+tr[now].r)>>1;
            if(y<=mid) update(lc,x,y,k);
            else if(x>=mid+1) update(rc,x,y,k);
            else {update(lc,x,mid,k); update(rc,mid+1,y,k);}
            tr[now].c=tr[lc].c+tr[rc].c;
        }
    }
    inline ll query(int now,int x,int y)
    {
        if(tr[now].l==x&&tr[now].r==y) return tr[now].c;
        else 
        {
            int lc=tr[now].lc,rc=tr[now].rc;
            pushdown(now);
            int mid=(tr[now].l+tr[now].r)>>1;
            if(y<=mid) return query(lc,x,y);
            else if(x>=mid+1) return query(rc,x,y);
            else return query(lc,x,mid)+query(rc,mid+1,y);
        }
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        bt(1,n);
        m=read();
        for(int i=1;i<=m;i++)
        {
            int p,x,y,k;
            p=read();
            if(p==1)
            {
                x=read();y=read();k=read();
                update(1,x,y,k);
            }else if(p==2)
            {
                x=read();y=read();
                printf("%lld
    ",query(1,x,y));
            }
        }
        return 0;
    }
        
  • 相关阅读:
    sqlplus时报Linux-x86_64 Error: 13: Permission denied
    thrift之TTransport层的缓存传输类TBufferedTransport和缓冲基类TBufferBase
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 队列操作
    Java实现 蓝桥杯 算法提高 队列操作
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 合并石子
  • 原文地址:https://www.cnblogs.com/bahl/p/7379748.html
Copyright © 2011-2022 走看看