【模板】線段樹(洛谷P3373)
阿新 • • 發佈:2018-11-08
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\n",query(1,1,n,x,y)); } } return 0; }