BZOJ1798:[AHOI2009]维护序列

浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1798

线段树区间加区间乘区间询问裸题。因为乘标记会影响加标记,所以优先下传乘标记。

时间复杂度:\(O(mlogn)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
using namespace std;

const int maxn=1e5+5;

int n,m,pps;
int a[maxn];

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

struct segment_tree {
	int tree[maxn<<2],add_tag[maxn<<2],mul_tag[maxn<<2];

	void updata(int p) {
		tree[p]=(tree[p<<1]+tree[p<<1|1])%pps;
	}

	void build(int p,int l,int r) {
		if(l==r) {
			tree[p]=a[l];
			return;
		}mul_tag[p]=1,add_tag[p]=0;//乘1加0等于本身
		int mid=(l+r)>>1;
		build(p<<1,l,mid);
		build(p<<1|1,mid+1,r);
		updata(p);
	}

	void add_add_tag(int p,int l,int r,int v) {
		tree[p]=(tree[p]+1ll*(r-l+1)*v%pps)%pps;
		add_tag[p]=(add_tag[p]+v)%pps;
	}

	void add_mul_tag(int p,int l,int r,int v) {
		tree[p]=1ll*tree[p]*v%pps;
		add_tag[p]=1ll*add_tag[p]*v%pps;
		mul_tag[p]=1ll*mul_tag[p]*v%pps;
	}

	void push_down(int p,int l,int r) {
		int mid=(l+r)>>1;
		if(mul_tag[p]!=1) {
			add_mul_tag(p<<1,l,mid,mul_tag[p]);
			add_mul_tag(p<<1|1,mid+1,r,mul_tag[p]);
			mul_tag[p]=1;
		}
		if(add_tag[p]) {
			add_add_tag(p<<1,l,mid,add_tag[p]);
			add_add_tag(p<<1|1,mid+1,r,add_tag[p]);
			add_tag[p]=0;
		}
	}

	void change_mul(int p,int l,int r,int L,int R,int v) {
		if(L<=l&&r<=R) {
			add_mul_tag(p,l,r,v);
			return;
		}
		int mid=(l+r)>>1;push_down(p,l,r);
		if(L<=mid)change_mul(p<<1,l,mid,L,R,v);
		if(R>mid)change_mul(p<<1|1,mid+1,r,L,R,v);
		updata(p);
	}

	void change_add(int p,int l,int r,int L,int R,int v) {
		if(L<=l&&r<=R) {
			add_add_tag(p,l,r,v);
			return;
		}
		int mid=(l+r)>>1;push_down(p,l,r);
		if(L<=mid)change_add(p<<1,l,mid,L,R,v);
		if(R>mid)change_add(p<<1|1,mid+1,r,L,R,v);
		updata(p);
	}

	int query(int p,int l,int r,int L,int R) {
		if(L<=l&&r<=R)return tree[p];
		int mid=(l+r)>>1,res=0;push_down(p,l,r);
		if(L<=mid)res=query(p<<1,l,mid,L,R);
		if(R>mid)res=(res+query(p<<1|1,mid+1,r,L,R))%pps;
		return res;
	}
}T;

int main() {
	n=read(),pps=read();
	for(int i=1;i<=n;i++)
		a[i]=read()%pps;
	T.build(1,1,n);m=read();
	for(int i=1;i<=m;i++) {
		int opt=read(),l=read(),r=read(),v;
		if(opt!=3)v=read();
		if(opt==1)T.change_mul(1,1,n,l,r,v);
		else if(opt==2)T.change_add(1,1,n,l,r,v);
		else printf("%d\n",T.query(1,1,n,l,r));
	}
	return 0;
}
posted @ 2018-11-12 17:14  AKMer  阅读(158)  评论(0编辑  收藏  举报