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

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1798


    题意概括

      一个序列n个数,支持3种操作:

      1. 询问区间和

      2. 修改区间: 每一个数加上一个数

      3. 修改区间: 每一个数乘上一个数

      n,m<=100000


    题解

      线段树。

      懒标记维护两个,一个是加的数,一个是乘的倍数,我写的是先乘后加。

      下传的时候也是先乘后加。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int N=100000+5;
    int n,m,q;
    LL mod,a[N];
    struct SegTree{
    	int L,R,S;
    	LL v,addp,addt;
    }t[N*4];
    void build(int rt,int le,int ri){
    	t[rt].L=le,t[rt].R=ri,t[rt].S=ri-le+1;
    	t[rt].addp=0,t[rt].addt=1;
    	if (le==ri){
    		t[rt].v=a[le];
    		return;
    	}
    	int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
    	build(ls,le,mid);
    	build(rs,mid+1,ri);
    	t[rt].v=(t[ls].v+t[rs].v)%mod;
    }
    void pushdown(int rt){
    	int ls=rt<<1,rs=ls|1;
    	LL &adp=t[rt].addp,&adt=t[rt].addt;
    	LL &Lv=t[ls].v,&Lp=t[ls].addp,&Lt=t[ls].addt;
    	LL &Rv=t[rs].v,&Rp=t[rs].addp,&Rt=t[rs].addt;
    	if (adt!=1){
    		Lv=Lv*adt%mod;
    		Lp=Lp*adt%mod;
    		Lt=Lt*adt%mod;
    		Rv=Rv*adt%mod;
    		Rp=Rp*adt%mod;
    		Rt=Rt*adt%mod;
    	}
    	if (adp!=0){
    		Lv=(Lv+adp*t[ls].S)%mod;
    		Lp=(Lp+adp)%mod;
    		Rv=(Rv+adp*t[rs].S)%mod;
    		Rp=(Rp+adp)%mod;
    	}
    	adp=0,adt=1;
    }
    void update(int rt,int le,int ri,int xle,int xri,LL x,int type){
    	if (le>xri||ri<xle)
    		return;
    	if (xle<=le&&ri<=xri){
    		if (type==1){
    			t[rt].v=t[rt].v*x%mod;
    			t[rt].addp=t[rt].addp*x%mod;
    			t[rt].addt=t[rt].addt*x%mod;
    		}
    		else {
    			t[rt].v=(t[rt].v+x*t[rt].S)%mod;
    			t[rt].addp=(t[rt].addp+x)%mod;
    		}
    		return;
    	}
    	pushdown(rt);
    	int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
    	update(ls,le,mid,xle,xri,x,type);
    	update(rs,mid+1,ri,xle,xri,x,type);
    	t[rt].v=(t[ls].v+t[rs].v)%mod;
    }
    LL query(int rt,int le,int ri,int xle,int xri){
    	if (le>xri||ri<xle)
    		return 0;
    	if (xle<=le&&ri<=xri)
    		return t[rt].v;
    	pushdown(rt);
    	int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
    	return (query(ls,le,mid,xle,xri)+query(rs,mid+1,ri,xle,xri))%mod;
    }
    int main(){
    	scanf("%d%lld",&n,&mod);
    	for (int i=1;i<=n;i++)
    		scanf("%lld",&a[i]),a[i]%=mod;
    	build(1,1,n);
    	scanf("%d",&m);
    	for (int i=1;i<=m;i++){
    		int type,L,R;
    		LL c;
    		scanf("%d%d%d",&type,&L,&R);
    		if (type==3)
    			printf("%lld
    ",query(1,1,n,L,R));
    		else {
    			scanf("%lld",&c);
    			update(1,1,n,L,R,c%mod,type);
    		}
    	}
    	return 0;
    }
      
    

      

  • 相关阅读:
    入门经典 第七章 7.3.3 二进制生成子集
    gdb调试方法简要总结
    Erlang_1
    hdu 1144
    创建一个类,重载运算符实现多项式的加,减,乘运算
    ubuntu12.04 iNodeClient 连校园网
    ftime使用
    CodeForce 264 A. Escape from Stones
    hdu 1161 Eddy's mistakes
    hdu 1064
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/7460713.html
Copyright © 2011-2022 走看看