zoukankan      html  css  js  c++  java
  • 线段树lazy操作

    本人自己出的一道题:

    已知有N个数,其中第i个数的只是a[i],对这i个数进行q个操作,每次先输入op,代表操作,若op==0,则输入x,y,求a[x]+......+a[y]的值。若op==1则 输入x,y,z,将a[x]......a[y]之间的每一个(包括a[x],a[y])加z。先输入n,q(n<=300000,q<=300000)
    接下来一行n个数,其中第i个数表示a[i]。接下来q行,先输入操作op,然后在对应地输入若op=0,则输出这个和,不然对应地进行操作。并且输出是一行一个数     (z<=10000000)

    样例输入:

    10 6
    1 2 3 4 5 6 7 8 9 10
    1 1 5 -5
    1 2 3 -6
    1 2 5 5 
    1 2 5 8
    1 4 9 -6
    0 2 7

    样例输出:23

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N=(1<<19)+10; 
    int l[N<<1],r[N<<1];
    long long sum[N<<1],lazy[N<<1];//lazy也可以写成add 
    int q,op,x,y,z,n;
    long long v[N],ans;
    void build(){//建树 
        int s=1;
        while(s<=n)s*=2;
        for(int i=s*2-1;i>=s;i--){
            l[i]=r[i]=i-s+1;
            sum[i]=v[i-s+1];lazy[i]=0;
        }
        for(int i=s-1;i>=1;i--){
            lazy[i]=0;
            l[i]=l[i*2];r[i]=r[i*2+1];
            sum[i]=sum[i*2+1]+sum[i*2];
        }
    }
    
    
    
    void pushdown(int i){//下方操作,将当前的lazy下放 
        if(lazy[i]){//这样下放,保证每次修改都能有效的进行 
            lazy[2*i]+=lazy[i];lazy[2*i+1]+=lazy[i];
            sum[2*i]+=(r[2*i]-l[2*i]+1)*lazy[i];
            sum[2*i+1]+=(r[2*i+1]-l[2*i+1]+1)*lazy[i];
            lazy[i]=0;
        }
    }
    
    
    
    
    void update(int l1,int r1,int i,int k){//更新操作,每次不要忘记下放 
        if(l1<=l[i]&&r[i]<=r1){
            lazy[i]+=k;
            sum[i]+=(r[i]-l[i]+1)*k;
            return ;
        }
        int mid=(l[i]+r[i])/2;
        pushdown(i);
        if(l1>mid)update(l1,r1,i*2+1,k);
        else if(r1<=mid)update(l1,r1,i*2,k);
        else {
            update(l1,mid,i*2,k);
            update(mid+1,r1,i*2+1,k);
        }
        sum[i]=sum[i*2]+sum[i*2+1];
    }
    void ask(int l1,int r1,int i){//询问操作,每次不要忘记下放 
        if(l1<=l[i]&&r[i]<=r1){
            ans+=sum[i];
            return ;
        }
        pushdown(i);
        int mid=(l[i]+r[i])/2;
        if(l1>mid)ask(l1,r1,i*2+1);
        else if(r1<=mid)ask(l1,r1,i*2);
        else {
            ask(l1,mid,i*2);
            ask(mid+1,r1,i*2+1);
        }
    }
    
    
    
    
    int main(){
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)scanf("%lld",&v[i]);
        build();
        for(int i=1;i<=q;i++){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d",&x,&y,&z);
                update(x,y,1,z);
            }
            else {
                scanf("%d%d",&x,&y);
                ans=0;ask(x,y,1);
                printf("%d
    ",ans);
            }
        }
    }
    
  • 相关阅读:
    Java 多态
    HDFS读写原理
    HDFS详解
    Servlet基础
    Tomcat
    HTTP简介
    JDBC技术
    final、finally和finalize
    java 中的权限修饰符
    进程、线程、线程状态、多线程实现方法
  • 原文地址:https://www.cnblogs.com/c201904xyorz/p/9990779.html
Copyright © 2011-2022 走看看