洛谷 P3373 【模板】線段樹 2
阿新 • • 發佈:2018-12-10
題目描述
如題,已知一個數列,你需要進行下面三種操作:
1.將某區間每一個數乘上x
2.將某區間每一個數加上x
3.求出某區間每一個數的和
輸入輸出格式
輸入格式:
第一行包含三個整數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取模所得的結果
輸出格式:
輸出包含若干行整數,即為所有操作3的結果。
輸入輸出樣例
輸入樣例#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
說明
時空限制:1000ms,128M
資料規模:
對於30%的資料:N<=8,M<=10
對於70%的資料:N<=1000,M<=10000
對於100%的資料:N<=100000,M<=100000
(資料已經過加強^_^)
樣例說明:
故輸出應為17、2(40 mod 38=2)
PS:還是一個線段樹的裸題,但是在區間修改的時候,他要乘上一個數,這時候懶標記下放,是要把下面要加的懶標記和要乘的懶標記的都要下放。細節看程式碼吧。
#include <iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<map> #include<queue> #include<set> #include<cmath> #include<stack> #include<string> const int maxn=1e5+10; const int mod=1e9+7; const int inf=1e8; #define me(a,b) memset(a,b,sizeof(a)) #define lowbit(x) x&(-x) typedef long long ll; using namespace std; ll num[maxn<<2],add[maxn<<2],ch[maxn<<2]; ll n,m,p; void init(int n) { for(int i=1; i<=4*n; i++) num[i]=add[i]=0,ch[i]=1; } void updata(int rt) { num[rt]=(num[rt<<1]+num[rt<<1|1])%p; } void build(int l,int r,int rt) { if(l==r) { scanf("%lld",&num[rt]); return ; } int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); updata(rt); } void push_down(int l,int r,int rt) { int m=(l+r)>>1; add[rt<<1]=(add[rt<<1]*ch[rt]+add[rt])%p; add[rt<<1|1]=(add[rt<<1|1]*ch[rt]+add[rt])%p; ch[rt<<1]=(ch[rt<<1]*ch[rt])%p; ch[rt<<1|1]=(ch[rt<<1|1]*ch[rt])%p; num[rt<<1]=(num[rt<<1]*ch[rt]+(m-l+1)*add[rt])%p; num[rt<<1|1]=(num[rt<<1|1]*ch[rt]+(r-m)*add[rt])%p; ch[rt]=1,add[rt]=0; } void push_data(int flog,int x,int L,int R,int l,int r,int rt) { if(L<=l&&R>=r) { if(flog==1) { add[rt]=(add[rt]*x)%p; ch[rt]=(ch[rt]*x)%p; num[rt]=(num[rt]*x)%p; } else { add[rt]=(add[rt]+x)%p; num[rt]=(num[rt]+(r-l+1)*x)%p; } return ; } int m=(l+r)>>1; push_down(l,r,rt); if(L<=m) push_data(flog,x,L,R,l,m,rt<<1); if(R>m) push_data(flog,x,L,R,m+1,r,rt<<1|1); updata(rt); } ll get_sum(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r) return num[rt]; int m=(l+r)>>1; push_down(l,r,rt); ll s=0; if(L<=m) s=(s+get_sum(L,R,l,m,rt<<1))%p; if(R>m) s=(s+get_sum(L,R,m+1,r,rt<<1|1))%p; return s%p; } int main() { cin>>n>>m>>p; init(n); build(1,n,1); while(m--) { int flog,x,y,k; scanf("%d",&flog); if(flog==3) { scanf("%d%d",&x,&y); printf("%lld\n",get_sum(x,y,1,n,1)); } else { scanf("%d%d%d",&x,&y,&k); push_data(flog,k,x,y,1,n,1); } } return 0; }