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\n",query(1,1,n,L,R));
		else {
			scanf("%lld",&c);
			update(1,1,n,L,R,c%mod,type);
		}
	}
	return 0;
}
  

  

 

posted @ 2017-08-31 21:50  zzd233  阅读(136)  评论(0编辑  收藏  举报