线段树模版(含动态开点)

【模板】线段树 2

题目描述

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

  • 将某区间每一个数乘上 \(x\)
  • 将某区间每一个数加上 \(x\)
  • 求出某区间每一个数的和。

输入格式

第一行包含三个整数 \(n,q,m\),分别表示该数列数字的个数、操作的总个数和模数。

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

接下来 \(q\) 行每行包含若干个整数,表示一个操作,具体如下:

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

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

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

输出格式

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

样例 #1

样例输入 #1

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

样例输出 #1

17
2

提示

【数据范围】

对于 \(30\%\) 的数据:\(n \le 8\)\(q \le 10\)
对于 \(70\%\) 的数据:\(n \le 10^3\)\(q \le 10^4\)
对于 \(100\%\) 的数据:\(1 \le n \le 10^5\)\(1 \le q \le 10^5\)

除样例外,\(m = 571373\)

(数据已经过加强 ^ _ ^)

样例说明:

故输出应为 \(17\)\(2\)\(40 \bmod 38 = 2\))。

线段树开long long容易超时!!!

如果你样例的第二个输出是 \(32\),那么请注意你是否在 Mul 中调用了 Add

#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define ull /*unsigned*/ long long
#define fd(i,a,b) for(int i=a,_i=b;i<=_i;i=-~i)
#define bd(i,a,b) for(int i=a,_i=b;i>=_i;i=~-i)
#define Db(a,b,ans) cout<<a<<';'<<b<<','<<ans<<endl
#define debug puts("-----------");
using namespace std;

const int N=1e6+509;
ll n,m,a[N],mod;

struct ST
{
	
	struct node
	{
		ll l,r,add,sum,mul;
		#define l(x) st[x].l
		#define r(x) st[x].r
		#define add(x) st[x].add
		#define sum(x) st[x].sum
		#define mul(x) st[x].mul
		#define ls(x) (x<<1)
		#define rs(x) (x<<1|1)
	}st[N<<1];
	
	inline void pushdown(int p)
	{
		if(add(p)==0&&mul(p)==1) return;
		sum(ls(p))=(sum(ls(p))*mul(p)%mod+add(p)*(r(ls(p))-l(ls(p))+1)%mod)%mod;
		sum(rs(p))=(sum(rs(p))*mul(p)%mod+add(p)*(r(rs(p))-l(rs(p))+1)%mod)%mod;
		mul(ls(p))=mul(ls(p))*mul(p)%mod;
		mul(rs(p))=mul(rs(p))*mul(p)%mod;
		add(ls(p))=(add(ls(p))*mul(p)%mod+add(p))%mod;
		add(rs(p))=(add(rs(p))*mul(p)%mod+add(p))%mod;
		add(p)=0;
		mul(p)=1;
	}
	
	inline void pushup(int p)
	{
		sum(p)=sum(ls(p))+sum(rs(p));
		sum(p)%=mod;
	}
	
	void build(int p,int l,int r)
	{
		l(p)=l,r(p)=r;
		add(p)=0,mul(p)=1;
		if(l==r)
		{
			sum(p)=a[r];
			return;
		}
		int mid=((r-l)>>1)+l;
		build(ls(p),l,mid);
		build(rs(p),mid+1,r);
		pushup(p);
	}
	
	void Add(int p,int l,int r,ll v)
	{
		if(l(p)>=l&&r(p)<=r)
		{
			add(p)=(add(p)+v)%mod;
			sum(p)=(sum(p)+v*(r(p)-l(p)+1)%mod)%mod;
			return;
		}
		pushdown(p);
		int mid=((r(p)-l(p))>>1)+l(p);
		if(l<=mid)	Add(ls(p),l,r,v);
		if(mid<r)	Add(rs(p),l,r,v);
		pushup(p);
	}
	
	void Mul(int p,int l,int r,ll v)
	{
		if(l(p)>=l&&r(p)<=r)
		{
			add(p)=(add(p)*v)%mod;
			mul(p)=(mul(p)*v)%mod;
			sum(p)=(sum(p)*v)%mod;
			return;
		}
		pushdown(p);
		int mid=((r(p)-l(p))>>1)+l(p);
		if(l<=mid)	Mul(ls(p),l,r,v);
		if(mid<r)	Mul(rs(p),l,r,v);
		pushup(p);
	}
	
	ll ask(int p,int l,int r)
	{
		if(l(p)>=l&&r(p)<=r) return sum(p);
		pushdown(p);
		int mid=((r(p)-l(p))>>1)+l(p);
		ll res=0;
		if(l<=mid)	res+=ask(ls(p),l,r)%mod;
		if(mid<r)	res+=ask(rs(p),l,r)%mod;
		return res%mod;
	}
	
}St;

signed main()
{
#ifdef FJ
	freopen("seq.in","r",stdin);
	freopen("seq.out","w",stdout);
#endif
//	ios::sync_with_stdio(0);
//	cin.tie(0); cout.tie(0);
	
	scanf("%lld%lld",&n,&mod);
	
	fd(i,1,n) scanf("%lld",&a[i]);
		
	St.build(1,1,n);
	
	scanf("%lld",&m);
	ll op,t,g,c;
	
	fd(i,1,m)
	{
		
		scanf("%lld",&op);
		
		if(op==1)
		{
			scanf("%lld%lld%lld",&t,&g,&c);
			St.Mul(1,t,g,c);
		}
		
		if(op==2)
		{
			scanf("%lld%lld%lld",&t,&g,&c);
			St.Add(1,t,g,c);
		}
		
		if(op==3)
		{
			scanf("%lld%lld",&t,&g);
			printf("%lld\n",St.ask(1,t,g));
		}
		
	}
	
	return 0;
}

upd on 2024.11.28

更新动态开点版本

#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define db(x) cout<<"DEBUG "<<#x<<" = "<<x<<endl;
#define endl '\n'
using namespace std;

//#define SIZE (1<<20)
//char In[SIZE],Out[SIZE],*p1=In,*p2=In,*p3=Out;
//#define getchar() (p1==p2&&(p2=(p1=In)+fread(In,1,SIZE,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c-48),c=getchar();}
	return x*f;
}
template<typename _T>
inline void write(_T x)
{
	static _T sta[35];int top=0;
	if(x<0) putchar('-'),x=-x;
	do{sta[top++]=x%10,x/=10;}while(x);
	while(top) putchar(sta[--top]+'0');
}

const int N=1e6+509,M=1e6+509;
int mod;
int n,a[N],q;

struct node
{
	int ls,rs,sum,add,mul,l,r;
	node(){ls=rs=sum=add=0,mul=1;}
	#define ls(p) t[p].ls
	#define rs(p) t[p].rs
	#define sum(p) t[p].sum
	#define add(p) t[p].add
	#define mul(p) t[p].mul
}t[N<<1];

int rt,tot;

inline void pushup(int p)
{
	sum(p)=sum(ls(p))+sum(rs(p));
}

inline void pushdown(int p,int l,int r)
{
	if(!ls(p)) ls(p)=++tot;
	if(!rs(p)) rs(p)=++tot;
	if(add(p)==0&&mul(p)==1) return;
	int mid=(l+r)>>1;
	
	(sum(ls(p))*=mul(p))%=mod;
	(sum(rs(p))*=mul(p))%=mod;
	
	(sum(ls(p))+=add(p)*(mid-l+1)%mod)%=mod;
	(sum(rs(p))+=add(p)*(r-mid)%mod)%=mod;
	
	(add(ls(p))*=mul(p))%=mod,(add(rs(p))*=mul(p))%=mod;
	(add(ls(p))+=add(p))%=mod,(add(rs(p))+=add(p))%=mod;
	
	(mul(ls(p))*=mul(p))%=mod,(mul(rs(p))*=mul(p))%=mod;
	
	add(p)=0,mul(p)=1;
}

void Add(int &p,int l,int r,int L,int R,int v)
{
	if(l>R||L>r) return;
	if(!p) p=++tot;
	if(L<=l&&r<=R)
	{
		(sum(p)+=v*(r-l+1)%mod)%=mod;
		(add(p)+=v)%=mod;
		return; 
	}
	pushdown(p,l,r);
	int mid=(r+l)>>1;
	Add(ls(p),l,mid,L,R,v);
	Add(rs(p),mid+1,r,L,R,v);
	pushup(p);
}

void Mul(int &p,int l,int r,int L,int R,int v)
{
	if(l>R||L>r) return;
	if(!p) p=++tot;
	if(L<=l&&r<=R)
	{
		(sum(p)*=v)%=mod;
		(mul(p)*=v)%=mod;
		(add(p)*=v)%=mod;
		return;
	}
	pushdown(p,l,r);
	int mid=(r+l)>>1;
	Mul(ls(p),l,mid,L,R,v);
	Mul(rs(p),mid+1,r,L,R,v);
	pushup(p);
}

int Ask(int &p,int l,int r,int L,int R)
{
	if(l>R||L>r) return 0;
	if(!p) p=++tot;
//	cerr<<"#"<<p<<' '<<l<<' '<<r<<' '<<sum(p)<<endl;
	if(L<=l&&r<=R) return sum(p);
	pushdown(p,l,r);
	int mid=(r+l)>>1,res=0;
	res+=Ask(ls(p),l,mid,L,R);
	res+=Ask(rs(p),mid+1,r,L,R);
	return res%mod;
}

signed main()
{
//#define FJ
#ifdef FJ
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
#else
//	freopen("A.in","r",stdin);
//	freopen("A.out","w",stdout);
#endif
//#define io
#ifdef io
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
#endif

	n=read(),q=read(),mod=read();
	
	fd(i,1,n) Add(rt,1,n,i,i,read());
	
	while(q--)
	{
		int op=read(),x=read(),y=read(),k;
		if(op!=3) k=read();
		if(op==1) Mul(rt,1,n,x,y,k);
		if(op==2) Add(rt,1,n,x,y,k);
		if(op==3) printf("%lld\n",Ask(rt,1,n,x,y));
//		fd(i,1,n) printf("%lld ",Ask(rt,1,n,i,i));
//		puts("");
	}	
	
	
	return 0;
}
posted @ 2024-07-06 16:20  whrwlx  阅读(2)  评论(0编辑  收藏  举报