题目描述
如题,已知一个数列,你需要进行下面三种操作:
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
(数据已经过加强^_^)
样例说明:
故输出应为17、2(40 mod 38=2)
做法:因为数据的关系,需要打lazy标记,考虑将加法和乘法的分开打,乘法优先更新可以保证不会错(复习线段树)。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define LL long long 5 #define rep(i,a,b) for(int i=a;i<=b;i++) 6 #define N 100007 7 using namespace std; 8 int n,m; 9 LL mo,a[N],mul[N*4],pul[N*4],t[N*4],ans=0; 10 11 inline LL Read(){ 12 LL s=0; 13 int zf=1; 14 char ch=getchar(); 15 for(;(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); 16 if (ch=='-') zf=-1,ch=getchar(); 17 for(;ch>='0'&&ch<='9';s=s*10+ch-'0',ch=getchar()); 18 return s*zf; 19 } 20 21 inline void Build(int p,int l,int r){ 22 mul[p]=1; 23 pul[p]=0; 24 if (l==r){ t[p]=a[l]%mo; return; } 25 int mid=(l+r)>>1; 26 Build(p<<1,l,mid); 27 Build(p<<1|1,mid+1,r); 28 t[p]=(t[p<<1]+t[p<<1|1])%mo; 29 } 30 31 inline void Pushdown(int p,int l,int r){ 32 int mid=(l+r)/2; 33 t[p<<1]=(t[p<<1]*mul[p]+pul[p]*(mid-l+1))%mo; 34 t[p<<1|1]=(t[p<<1|1]*mul[p]+pul[p]*(r-mid))%mo; 35 mul[p<<1]=(mul[p<<1]*mul[p])%mo; 36 mul[p<<1|1]=(mul[p<<1|1]*mul[p])%mo; 37 pul[p<<1]=(pul[p<<1]*mul[p]+pul[p])%mo; 38 pul[p<<1|1]=(pul[p<<1|1]*mul[p]+pul[p])%mo; 39 pul[p]=0; 40 mul[p]=1; 41 } 42 43 inline void Upmul(int p,int l,int r,int ax,int ay,LL num){ 44 if(l>ay||r<ax) return; 45 if(ax<=l&&r<=ay){ 46 t[p]=(t[p]*num)%mo; 47 mul[p]=(mul[p]*num)%mo; 48 pul[p]=(pul[p]*num)%mo; 49 return; 50 } 51 Pushdown(p,l,r); 52 int mid=(l+r)>>1; 53 Upmul(p<<1,l,mid,ax,ay,num); 54 Upmul(p<<1|1,mid+1,r,ax,ay,num); 55 t[p]=(t[p<<1]+t[p<<1|1])%mo; 56 } 57 58 inline void Uppul(int p,int l,int r,int ax,int ay,LL num){ 59 if(l>ay||r<ax) return; 60 if(ax<=l&&r<=ay){ 61 pul[p]=(pul[p]+num)%mo; 62 t[p]=(t[p]+num*(r-l+1))%mo; 63 return; 64 } 65 Pushdown(p,l,r); 66 int mid=(l+r)>>1; 67 Uppul(p<<1,l,mid,ax,ay,num); 68 Uppul(p<<1|1,mid+1,r,ax,ay,num); 69 t[p]=(t[p<<1]+t[p<<1|1])%mo; 70 71 } 72 73 inline void Count(int p,int l,int r,int ax,int ay){ 74 if (l>ay||r<ax) return; 75 if (ax<=l&&r<=ay){ 76 ans=(ans+t[p])%mo; 77 return; 78 } 79 int mid=(l+r)>>1; 80 Pushdown(p,l,r); 81 Count(p<<1,l,mid,ax,ay); 82 Count(p<<1|1,mid+1,r,ax,ay); 83 } 84 85 int main(){ 86 n=Read(),m=Read(),mo=Read(); 87 rep(i,1,n) a[i]=Read(); 88 Build(1,1,n); 89 int ain,x,y,k; 90 for(;m--;){ 91 ain=Read(); 92 if(ain==1){ 93 x=Read(),y=Read(),k=Read(); 94 Upmul(1,1,n,x,y,k); 95 } 96 if(ain==2){ 97 x=Read(),y=Read(),k=Read(); 98 Uppul(1,1,n,x,y,k); 99 } 100 if(ain==3){ 101 x=Read(),y=Read(); 102 ans=0; 103 Count(1,1,n,x,y); 104 printf("%lld\n",ans); 105 } 106 } 107 }