(模板)线段树2

(模板)线段树2

题目描述

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

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的结果。

N<=100000,M<=100000

  • 注意:
  • 先加后乘,乘法标记要初始化为1,k可能是负数,所以最好+s,再%s

   代码:

 

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cctype>
  5 using namespace std;
  6 
  7 inline int read()
  8 {
  9     int x(0),f(1); char ch;
 10     while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
 11     while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
 12     return f*x;
 13 }
 14 #define res register int
 15 typedef long long LL; 
 16 const int N=100000+5;
 17 struct SegTree{
 18     int l,r; LL val,add,mul;
 19     #define l(x) tr[x].l
 20     #define r(x) tr[x].r
 21     #define val(x) tr[x].val
 22     #define mul(x) tr[x].mul
 23     #define add(x) tr[x].add
 24     #define len(x) (tr[x].r-tr[x].l+1)
 25 }tr[N<<2];
 26 int a[N],n,m,s;
 27 
 28 inline void push_up(int p)
 29 {
 30     val(p)=(val(p<<1)+val(p<<1|1))%s;
 31 }
 32 
 33 inline void build(int p,int l,int r)
 34 {    
 35     mul(p)=1;
 36     l(p)=l; r(p)=r; 
 37     if(l==r) { val(p)=a[l];  return ;}
 38     int mid=(l+r)>>1;
 39     build(p<<1,l,mid); build(p<<1|1,mid+1,r);
 40     push_up(p);
 41 }
 42 
 43 inline void push_down(int p)
 44 {
 45     if(add(p)||mul(p)!=1)
 46     {
 47         val(p<<1)=  (val(p<<1)*mul(p) + add(p)*len(p<<1)+s)%s;
 48         val(p<<1|1)=(val(p<<1|1) * mul(p) + add(p)*len(p<<1|1)+s)%s;
 49         mul(p<<1)=  (mul(p) * mul(p<<1)+s)%s;
 50         mul(p<<1|1)=(mul(p) * mul(p<<1|1)+s)%s;
 51         add(p<<1)=  (add(p<<1) * mul(p) + add(p)+s)%s;
 52         add(p<<1|1)=(add(p<<1|1)*mul(p) + add(p)+s)%s;
 53         add(p)=0; mul(p)=1;
 54     }
 55 }
 56 
 57 inline void change1(int p,int l,int r,int d)
 58 {
 59     if(l<=l(p) && r(p)<=r) {
 60         val(p)=(val(p)*d)%s;
 61         mul(p)=(mul(p)*d)%s;
 62         add(p)=(add(p)*d)%s; 
 63         return ;
 64     }
 65     push_down(p);
 66     int mid=(l(p)+r(p))>>1;
 67     if(l<=mid) change1(p<<1,l,r,d);
 68     if(r>mid)  change1(p<<1|1,l,r,d);
 69     push_up(p);
 70 }
 71 
 72 inline void change2(int p,int l,int r,int d)
 73 {
 74     if(l<=l(p) && r(p)<=r) {
 75         val(p)=(val(p)+(LL)d*len(p))%s; 
 76         add(p)=(add(p)+d)%s; return ;
 77     }
 78     push_down(p);
 79     int mid=(l(p)+r(p))>>1;
 80     if(l<=mid) change2(p<<1,l,r,d);
 81     if(r>mid)  change2(p<<1|1,l,r,d);
 82     push_up(p);
 83 }
 84 
 85 LL ask(int p,int l,int r)
 86 {
 87     if(l<=l(p) && r(p)<=r) return val(p);
 88     push_down(p); int mid=(l(p)+r(p))>>1;
 89     LL tmp(0);
 90     if(l<=mid) tmp+=ask(p<<1,l,r)%s;
 91     if(r>mid)  tmp+=ask(p<<1|1,l,r)%s;
 92     return tmp%s;
 93 }
 94 int main()
 95 {
 96     n=read(); m=read(); s=read();
 97     for(res i=1 ; i<=n ; i++)    a[i]=read();
 98     build(1,1,n);
 99     for(res i=1 ; i<=m ; i++)
100     {
101         int op=read(),x=read(),y=read();
102         if(op==1)
103         {
104             int z=read(); change1(1,x,y,z);
105         }
106         else if(op==2)
107         {
108             int z=read(); change2(1,x,y,z);
109         }
110         else if(op==3)
111             printf("%lld\n",ask(1,x,y));
112     }
113     return 0;
114 }
View Code

 

posted @ 2019-02-12 14:41  孑行  阅读(129)  评论(0编辑  收藏  举报