zoukankan      html  css  js  c++  java
  • 线段树历史版本和

    假设当前进行到操作 $m$.     

    1. 将区间 $[l,r]$ 每个数加上 $v$.   

    2. 询问当前区间 $[l,r]$ 的和.  

    3. 令 $S(l,r,x)$ 代表 $[l,r]$ 区间在时刻 $x$ 时之和,求 $sum_{i=0}^{m} S(l,r,i)$.  

    题解:  

    对于一个区间,我们要求当前区间和以及所有历史时刻之和.  

    考虑维护 $sum, sumh$ 分别表示当前和以及历史和.          

    如果没有加法标记,我们可以直接存一个 $tag$,表示 $sumh leftarrow sumh+tag imes sum.$       

    然后我们发现存在加法标记的情况下要先下传加法标记,再下传 $tag.$    

    考虑下传加法标记:

    $sum leftarrow sum+len imes v$  

    $add leftarrow add+v$

    $sumh leftarrow sumh+tag imes sum$.  

    对于点 $x$ 来说,假设原来有 $v1,tag1$,那么现在变为 $v1+v$,$tag1$.     

    而根据定义,$tag1$ 应该只和 $v1$ 结合,所有加多了一部分,那么就再设标记 $addh$ 表示 $sumh$ 需要减去的值就好了.  

    下传标记的顺序是:$add$,$addh$,$tag$.   

    code:   

    #include <cstdio> 
    #include <cstring>  
    #include <algorithm>    
    #define N 100008   
    #define ll long long   
    #define lson now<<1  
    #define rson now<<1|1  
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;  
    int a[N],n,m;                    
    struct data {  
        int len;    
        ll sum,add,sumh,tag,addh;   
    }s[N];              
    void pushup(int now) {  
        s[now].sum=s[lson].sum+s[rson].sum;     
        s[now].sumh=s[lson].sumh+s[rson].sumh;    
    }       
    void mark_adh(int now,ll v,int t) {   
        s[now].addh+=v;    
        if(t) s[now].sumh+=v*s[now].len;     
    }
    void mark_add(int now,ll v) {        
        if(s[now].tag) {    
            mark_adh(now,-v*s[now].tag,0);     
        }
        s[now].add+=v;     
        s[now].sum+=1ll*s[now].len*v;                     
    }  
    void mark_tag(int now,ll v) {  
        s[now].tag+=v;       
        s[now].sumh+=s[now].sum*v;    
    }
    void pushdown(int now) {   
        if(s[now].add) {   
            mark_add(lson,s[now].add);  
            mark_add(rson,s[now].add);    
            s[now].add=0;  
        }   
        if(s[now].addh) {   
            mark_adh(lson,s[now].addh,1);   
            mark_adh(rson,s[now].addh,1);  
            s[now].addh=0;  
        }   
        if(s[now].tag) {    
            mark_tag(lson,s[now].tag);  
            mark_tag(rson,s[now].tag);  
            s[now].tag=0;   
        }
    }
    void build(int l,int r,int now) {  
        s[now].len=r-l+1;      
        if(l==r) {  
            s[now].sum=a[l];  
            s[now].sumh=a[l];   
            return; 
        } 
        int mid=(l+r)>>1;  
        build(l,mid,lson); 
        build(mid+1,r,rson); 
        pushup(now);  
    }
    void update(int l,int r,int now,int L,int R,int v) {  
        if(l>=L&&r<=R) {  
            mark_add(now,v);   
            return;  
        }  
        pushdown(now);  
        int mid=(l+r)>>1;   
        if(L<=mid)  update(l,mid,lson,L,R,v);  
        if(R>mid)   update(mid+1,r,rson,L,R,v);    
        pushup(now);  
    }
    ll query(int l,int r,int now,int L,int R) {    
        if(l>=L&&r<=R) {  
            return s[now].sumh;  
        }  
        pushdown(now);  
        int mid=(l+r)>>1;      
        ll re=0; 
        if(L<=mid)  re+=query(l,mid,lson,L,R);  
        if(R>mid)   re+=query(mid+1,r,rson,L,R);   
        return re;   
    }      
    int main() {    
        // setIO("input");     
        // freopen("de.out","w",stdout);  
        scanf("%d%d",&n,&m);   
        for(int i=1;i<=n;++i) {  
            scanf("%d",&a[i]);   
        }   
        build(1,n,1);   
        int x,y,z,l,r;  
        for(int i=1;i<=m;++i) {
            scanf("%d%d%d",&l,&r,&x);   
            update(1,n,1,l,r,1ll*x);   
            mark_tag(1,1);   
            scanf("%d%d",&x,&y);
            printf("%lld
    ",query(1,n,1,x,y));   
        }
        return 0; 
    }
    

      

    暴力: 

    #include <bits/stdc++.h>           
    #define N 1002 
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin)  
    using namespace std;      
    ll a[N][N],sum[N][N];  
    int main() {  
        setIO("input");      
        freopen("input.out","w",stdout);  
        int n,m; 
        scanf("%d%d",&n,&m);        
        for(int i=1;i<=n;++i) scanf("%lld",&a[0][i]),sum[0][i]=a[0][i];     
        for(int i=1;i<=m;++i) {        
            int l,r,x,L,R;   
            scanf("%d%d%d",&l,&r,&x);    
            for(int j=1;j<=n;++j) a[i][j]=a[i-1][j];  
            for(int j=l;j<=r;++j) a[i][j]+=1ll*x;     
            for(int j=1;j<=n;++j) sum[i][j]=sum[i-1][j]+a[i][j];           
            scanf("%d%d",&L,&R);  
            ll s=0;  
            for(int j=L;j<=R;++j) s+=sum[i][j];     
            printf("%lld
    ",s);   
        }
        return 0; 
    }    
    /*  
    input:
    5 3
    1 2 3 4 5  
    1 1 1 2 4
    1 3 2 2 4
    1 3 3 1 5 
    output:   
    18
    31
    84   
    */  
    

      

    数据生成器及对拍:  

    #include <bits/stdc++.h> 
    using namespace std;    
    int RAN(int p) { return rand()%p+1; }  
    void make() {    
        FILE *fp=fopen("input.in","w");   
        int n=1000,m=1000;      
        fprintf(fp,"%d %d
    ",n,m);  
        for(int i=1;i<=n;++i) {
            fprintf(fp,"%d ",RAN(1000));   
        }
        fprintf(fp,"
    ");   
        for(int i=1;i<=m;++i) {  
            int l=RAN(n),r=RAN(n);  
            if(l>r) swap(l,r);    
            fprintf(fp,"%d %d %d ",l,r,RAN(1000));  
            int L=RAN(n),R=RAN(n);  
            if(L>R) swap(L,R);  
            fprintf(fp,"%d %d
    ",L,R);  
        }
        fclose(fp);    
    }
    void gen() {  
        make();        
    }
    int main() {    
        system("g++ std.cpp -o std.exe -g -O2 -std=c++11 -Wl,-stack=512000000");   
        system("g++ code.cpp -o code.exe -g -O2 -std=c++11 -Wl,-stack=512000000");    
        srand(time(NULL)); 
        rand();    
        int times=0;   
        while(1)  {  
            gen(); 
            system("std.exe < input.in > de.out");   
            int s=clock();  
            system("code.exe < input.in > input.out");  
            int t=clock();        
            if(system("fc input.out de.out > FC.out")) {  
                printf("WA
    ");   
                break; 
            } 
            else {   
                printf("%d : AC : %d
    ",++times,t-s);  
            }
        }
        return 0; 
    }
    

      

      

  • 相关阅读:
    深入了解抽象类和接口
    关于Hibernate查询对象调用set方法自动同步到数据库解决方案
    【鸽子的迷信(一)】python导入由excel文件改后缀变成的csv文件出现乱码错误(ParserError:Error tokenizing data. C error:)
    《计算机操作系统》CH1操作系统引论思维导图整理
    IntelliJ IDEA创建一个Maven项目
    C++实验三
    小练习
    C++实验二
    C++的ch1&ch2的整理
    C++实验一
  • 原文地址:https://www.cnblogs.com/guangheli/p/13274276.html
Copyright © 2011-2022 走看看