《告诫后人》
查看原帖
《告诫后人》
557510
AzureHair楼主2022/9/23 19:20
#include<bits/stdc++.h>
using namespace std;
struct node
{
	long long l,r,add,add2,pre;
}t[200014];
long long c[100004];
long long n,m,mod;
void build(long long x,long long a,long long b)
{
	t[x].l=a;t[x].r=b;t[x].add2=1; 
	if(a==b)
	{
		t[x].pre=c[a]%mod;
		return ;
	}
	long long mid=a+b>>1;
	build(x*2,a,mid);
	build(x*2+1,mid+1,b);
	t[x].pre=(t[x*2].pre+t[x*2+1].pre)%mod;
	return ;
}
void spread(long long x)
{
	t[x*2].pre=(t[x].add2*t[x*2].pre)%mod;
	t[x*2+1].pre=(t[x].add2*t[x*2+1].pre)%mod;
	t[x*2].pre=(t[x*2].pre+t[x].add*(t[x*2].r-t[x*2].l+1))%mod;
	t[x*2+1].pre=(t[x*2+1].pre+t[x].add*(t[x*2+1].r-t[x*2+1].l+1))%mod;
	t[x*2].add2=(t[x*2].add2*t[x].add2)%mod;
	t[x*2+1].add2=(t[x*2+1].add2*t[x].add2)%mod;
	t[x*2].add=(t[x*2].add*t[x].add2+t[x].add)%mod;
	t[x*2+1].add=(t[x*2+1].add*t[x].add2+t[x].add)%mod;
	t[x].add=0;t[x].add2=1;
}
void change(long long x,long long a,long long b,long long s)
{
	if(a<=t[x].l&&b>=t[x].r)
	{
		t[x].pre=(t[x].pre+s*(t[x].r-t[x].l+1))%mod;
		t[x].add=(t[x].add+s)%mod;
		return ;
	}
	spread(x);
	t[x].pre=t[x*2].pre+t[x*2+1].pre;
	long long mid=(t[x].l+t[x].r)>>1;
	if(a<=mid)
	{
		change(x*2,a,b,s);
	}
	if(b>mid)
	{
		change(x*2+1,a,b,s);
	}
	t[x].pre=(t[x*2].pre+t[x*2+1].pre)%mod;
	return ;
}
void qchange(long long x,long long a,long long b,long long s)
{
	if(a<=t[x].l&&b>=t[x].r)
	{
		t[x].pre=(s*t[x].pre)%mod;
		t[x].add2=(t[x].add2*s)%mod;
		t[x].add=(t[x].add*s)%mod;
		return ;
	}
	spread(x);
	t[x].pre=(t[x*2].pre+t[x*2+1].pre)%mod;
	long long mid=(t[x].l+t[x].r)>>1;
	if(a<=mid)
	{
		qchange(x*2,a,b,s);
	}
	if(b>mid)
	{
		qchange(x*2+1,a,b,s);
	}
	t[x].pre=(t[x*2].pre+t[x*2+1].pre)%mod;
	return ; 
}
long long ask(long long x,long long a,long long b)
{
	if(a<=t[x].l&&b>=t[x].r)
	{
		return t[x].pre;
	}
	spread(x);
	long long ans=0;
	long long mid=t[x].l+t[x].r>>1;
	if(a<=mid)
	{
		ans+=(ask(x*2,a,b))%mod;
	}
	if(b>mid)
	{
		ans+=(ask(x*2+1,a,b))%mod;
	}
	return ans;
}
int main()
{
	cin>>n>>m>>mod;
	for(int i=1;i<=n;i++)
	{
		cin>>c[i];
	}
	build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		int q;
		cin>>q;
		if(q==2)
		{
			int x,y,z;
			cin>>x>>y>>z;
			change(1,x,y,z);
		}
		if(q==3)
		{
			int x,y;
			cin>>x>>y;
			cout<<ask(1,x,y)%mod<<endl;
		}
		if(q==1)
		{
			int x,y,z;
			cin>>x>>y>>z;
			qchange(1,x,y,z);
		}
	}
	return 0;
}

线段树的结构体一定要开4倍(本人开了2倍调了2个星期)【哭死】

2022/9/23 19:20
加载中...