洛谷 3373 线段树练习

题目描述

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

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)

做法:因为数据的关系,需要打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 }
View Code

猜你喜欢

转载自www.cnblogs.com/traveller-ly/p/9594285.html
今日推荐