zoukankan      html  css  js  c++  java
  • bzoj1798: [Ahoi2009]Seq 维护序列seq 线段树

    题目传送门

    这道题就是线段树 先传乘法标记再传加法

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int M=400010;
    LL read(){
        LL ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    LL n,m,mod,L,R;
    struct node{
        int l,r;
        LL sum,add,mt;
    }tr[M];
    void up(int x){tr[x].sum=(tr[x<<1].sum+tr[x<<1^1].sum)%mod;}
    void cal(LL x,LL mt,LL w){
        if(!x) return ;
        LL l=tr[x].r-tr[x].l+1;
        tr[x].sum=(tr[x].sum*mt+w*l)%mod;
        tr[x].add=(tr[x].add*mt+w)%mod;
        tr[x].mt=tr[x].mt*mt%mod;
    }
    void down(LL x){
        if(tr[x].add||tr[x].mt!=1){
            cal(x<<1,tr[x].mt,tr[x].add);
            cal(x<<1^1,tr[x].mt,tr[x].add);
            tr[x].add=0; tr[x].mt=1;
        }
    }
    void build(LL x,LL l,LL r){
        tr[x].l=l; tr[x].r=r; tr[x].mt=1;
        if(l==r){tr[x].sum=read(); return ;}
        int mid=(l+r)>>1;
        build(x<<1,l,mid); build(x<<1^1,mid+1,r);
        up(x);
    }
    void push_mm(LL x,LL w){
        if(L<=tr[x].l&&tr[x].r<=R){cal(x,w,0); return ;}
        int mid=(tr[x].l+tr[x].r)>>1;
        down(x);
        if(L<=mid) push_mm(x<<1,w);
        if(R>mid) push_mm(x<<1^1,w);
        up(x);
    }
    void push_add(LL x,LL w){
        if(L<=tr[x].l&&tr[x].r<=R){cal(x,1,w); return ;}
        int mid=(tr[x].l+tr[x].r)>>1;
        down(x);
        if(L<=mid) push_add(x<<1,w);
        if(R>mid) push_add(x<<1^1,w);
        up(x);
    }
    LL push_sum(LL x){
        if(L<=tr[x].l&&tr[x].r<=R) return tr[x].sum;
        int mid=(tr[x].l+tr[x].r)>>1;
        down(x);
        LL ans=0;
        if(L<=mid) ans=(ans+push_sum(x<<1))%mod;
        if(R>mid)  ans=(ans+push_sum(x<<1^1))%mod;
        return ans;
    }
    int main()
    {
        LL k,w; 
        n=read(); mod=read(); 
        build(1,1,n); 
        m=read();
        for(int i=1;i<=m;i++){
            k=read(); L=read(); R=read();
            if(k==1) w=read(),push_mm(1,w);
            if(k==2) w=read(),push_add(1,w);
            if(k==3) printf("%lld
    ",push_sum(1)%mod);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    hdu1787GCD Again<欧拉函数>
    uva11300Spreading the Wealth<数学>
    Java基础之Calendar应用:每周三、六休息,从某个日期起至今休息多少天?
    Java基础之Runtime类
    Java基础之Calendar对象
    Java基础之集合转换为数组
    Java基础之数组转换为集合
    Java基础之高级(增强的)For循环(foreach)
    Java基础之Date对象的使用
    Java基础之可变参数
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7087317.html
Copyright © 2011-2022 走看看