【模板】线段树(洛谷P3373)

Description

  如题,已知一个数列,你需要进行下面三种操作:

  1.将某区间每一个数乘上(x)

  2.将某区间每一个数加上(x)

  3.求出某区间每一个数的和

Input

  第一行包含三个整数(N)(M)(P),分别表示该数列数字的个数、操作的总个数和模数。

  第二行包含(N)个用空格分隔的整数,其中第(i)个数字表示数列第i项的初始值。

  接下来(M)行每行包含3或4个整数,表示一个操作,具体如下:

  操作1: 格式:(1 x y  k) 含义:将区间([x,y])内每个数乘上(k)

  操作2: 格式:(2  x y k) 含义:将区间([x,y])内每个数加上(k)

  操作3: 格式:(3  x  y) 含义:输出区间([x,y])内每个数的和对(P)取模所得的结果

Output

  输出包含若干行整数,即为所有操作3的结果。

Solution

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100000;
long long sum[4*N+10],multag[4*N+10],addtag[4*N+10],a[N+10];
int n,m,Mod,opt,x,y,k;
inline long long read()
{
	long long ans=0,f=1;
	char ch=getchar();
	while (ch<'0' || ch>'9')
	{
		if (ch=='-') f=-1;
		ch=getchar();
	}
	while (ch>='0' && ch<='9')
	{
		ans=ans*10+ch-'0';
		ch=getchar();
	}
	return ans*f;
}
long long mo(long long x,long long y)
{
	return x+y>=Mod?x+y-Mod:x+y;
}
void pushdown(int p,int l,int r)
{
	int mid=(l+r)>>1;
	if (multag[p]!=1)
	{
		sum[p<<1]=sum[p<<1]*multag[p]%Mod;
		sum[p<<1|1]=sum[p<<1|1]*multag[p]%Mod;
		multag[p<<1]=multag[p<<1]*multag[p]%Mod;
		multag[p<<1|1]=multag[p<<1|1]*multag[p]%Mod;
		addtag[p<<1]=addtag[p<<1]*multag[p]%Mod;
		addtag[p<<1|1]=addtag[p<<1|1]*multag[p]%Mod;
		multag[p]=1;
	}
	if (addtag[p])
	{
		sum[p<<1]=mo(sum[p<<1],addtag[p]*(mid-l+1)%Mod);
		sum[p<<1|1]=mo(sum[p<<1|1],addtag[p]*(r-mid)%Mod);
		addtag[p<<1]=mo(addtag[p<<1],addtag[p]);
		addtag[p<<1|1]=mo(addtag[p<<1|1],addtag[p]);
		addtag[p]=0;
	}
}
void build(int p,int l,int r)
{
	if (l==r)
	{
		sum[p]=a[l];
		multag[p]=1,addtag[p]=0;
		return;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	sum[p]=mo(sum[p<<1],sum[p<<1|1]);
	multag[p]=1;addtag[p]=0;
}
void modify_mul(int p,int l,int r,int i,int j,long long v)
{
	if (l==i && r==j)
	{
		sum[p]=sum[p]*v%Mod;
		multag[p]=multag[p]*v%Mod;
		addtag[p]=addtag[p]*v%Mod;
		return;
	}
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if (j<=mid) modify_mul(p<<1,l,mid,i,j,v);
	else if (i>mid) modify_mul(p<<1|1,mid+1,r,i,j,v);
	else
	{
		modify_mul(p<<1,l,mid,i,mid,v);
		modify_mul(p<<1|1,mid+1,r,mid+1,j,v);
	}
	sum[p]=mo(sum[p<<1],sum[p<<1|1]);
}
void modify_add(int p,int l,int r,int i,int j,long long v)
{
	if (l==i && r==j)
	{
		sum[p]=mo(sum[p],v*(r-l+1)%Mod);
		addtag[p]=mo(addtag[p],v);
		return;
	}
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if (j<=mid) modify_add(p<<1,l,mid,i,j,v);
	else if (i>mid) modify_add(p<<1|1,mid+1,r,i,j,v);
	else
	{
		modify_add(p<<1,l,mid,i,mid,v);
		modify_add(p<<1|1,mid+1,r,mid+1,j,v);
	}
	sum[p]=mo(sum[p<<1],sum[p<<1|1]);
}
long long query(int p,int l,int r,int i,int j)
{
	if (l==i && r==j) return sum[p];
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if (j<=mid) return query(p<<1,l,mid,i,j);
	else if (i>mid) return query(p<<1|1,mid+1,r,i,j);
	else
	{
		return mo(query(p<<1,l,mid,i,mid),query(p<<1|1,mid+1,r,mid+1,j));
	}
}
int main()
{
	n=read(),m=read(),Mod=read();
	for (int i=1;i<=n;i++) a[i]=read(),a[i]%=Mod;
	build(1,1,n);
	while (m--)
	{
		opt=read();
		if (opt==1)
		{
			x=read(),y=read(),k=read();
			k%=Mod;
			modify_mul(1,1,n,x,y,k);
		}
		if (opt==2)
		{
			x=read(),y=read(),k=read();
			k%=Mod;
			modify_add(1,1,n,x,y,k);
		}
		if (opt==3)
		{
			x=read(),y=read();
			printf("%lld
",query(1,1,n,x,y));
		}
	}
	return 0;
}

原文地址:https://www.cnblogs.com/Code-Geass/p/9927318.html