P3373 线段树乘法模板 P2023 [AHOI2009]维护序列
Posted bxd123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3373 线段树乘法模板 P2023 [AHOI2009]维护序列相关的知识,希望对你有一定的参考价值。
题目描述
如题,已知一个数列,你需要进行下面三种操作:
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的结果。
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
多一个乘法标记 调的欲仙欲死
记住一个原则 先乘后加!!!
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 const int N=100000; int n,mod; ll sum[N<<2],col[N<<2],mul[N<<2]; void up(int pos) { sum[pos]=sum[pos<<1]+sum[pos<<1|1]; sum[pos]%=mod; } void down(int pos,int m) { sum[pos<<1]=(sum[pos<<1]*mul[pos])%mod; sum[pos<<1|1]=(sum[pos<<1|1]*mul[pos])%mod; sum[pos<<1]=(sum[pos<<1]+col[pos]*(m-(m>>1)))%mod; sum[pos<<1|1]=(sum[pos<<1|1]+col[pos]*(m>>1))%mod; mul[pos<<1]=(mul[pos<<1]*mul[pos])%mod; mul[pos<<1|1]=(mul[pos<<1|1]*mul[pos])%mod; col[pos<<1]=(col[pos<<1]*mul[pos])%mod; col[pos<<1|1]=(col[pos<<1|1]*mul[pos])%mod; col[pos<<1]=(col[pos<<1]+col[pos])%mod; col[pos<<1|1]=(col[pos<<1|1]+col[pos])%mod; col[pos]=0; mul[pos]=1; } void build(int l,int r,int pos) { col[pos]=0; mul[pos]=1; if(l==r) { scanf("%lld",&sum[pos]); sum[pos]%=mod; return ; } int m=(l+r)>>1; build(lson); build(rson); up(pos); } void add(int L,int R,int v,int l,int r,int pos) { if(L<=l&&r<=R) { sum[pos]+=(r-l+1)*v; sum[pos]%=mod; col[pos]+=v; col[pos]%=mod; return ; } down(pos,r-l+1); int m=(l+r)>>1; if(L<=m)add(L,R,v,lson); if(R>m)add(L,R,v,rson); up(pos); } void mu(int L,int R,int v,int l,int r,int pos) { if(L<=l&&r<=R) { sum[pos]*=v;sum[pos]%=mod; col[pos]*=v;col[pos]%=mod; mul[pos]*=v;mul[pos]%=mod; return ; } down(pos,r-l+1); int m=(l+r)>>1; if(L<=m)mu(L,R,v,lson); if(R>m) mu(L,R,v,rson); up(pos); } ll query(int L,int R,int l,int r,int pos) { if(L<=l&&r<=R) { return sum[pos]%mod; } ll ans=0; down(pos,r-l+1); int m=(l+r)>>1; if(L<=m)ans+=query(L,R,lson)%mod; if(R>m) ans+=query(L,R,rson)%mod; return ans%mod; } int main() { int m; RIII(n,m,mod); build(1,n,1); while(m--) { int x,a,b,c;RI(x); if(x==1) { RIII(a,b,c); mu(a,b,c,1,n,1); } else if(x==2) { RIII(a,b,c); add(a,b,c,1,n,1); } else { RII(a,b); cout<<query(a,b,1,n,1)<<endl; } } }
以上是关于P3373 线段树乘法模板 P2023 [AHOI2009]维护序列的主要内容,如果未能解决你的问题,请参考以下文章