洛谷P3373 【模板】线段树 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的结果。

输入输出样例

输入样例#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)

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 int n,m,p,judge,x,y,k;
  5 long long a[100007];
  6 long long read()
  7 {
  8     long long x=0,f=1;
  9     char ch=getchar();
 10     while(ch>'9'||ch<'0')
 11     {
 12         if(ch=='-')
 13             f=-1;
 14         ch=getchar();
 15     }
 16     while(ch>='0'&&ch<='9')
 17     {
 18         x=x*10+ch-'0';
 19         ch=getchar();
 20     }
 21     return x*f;
 22 }
 23 struct node
 24 {
 25     long long v,mul,add;
 26 } st[400007];
 27 void build(int root, int l, int r)
 28 {
 29     st[root].mul=1;
 30     st[root].add=0;
 31     if(l==r)
 32         st[root].v=a[l];
 33     else
 34     {
 35         int m=(l+r)/2;
 36         build(root*2, l, m);
 37         build(root*2+1, m+1, r);
 38         st[root].v=st[root*2].v+st[root*2+1].v;
 39     }
 40     st[root].v%=p;
 41     return ;
 42 }
 43 void pushdown(int root, int l, int r)
 44 {
 45     int m=(l+r)/2;
 46     st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(m-l+1))%p;
 47     st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-m))%p;
 48     st[root*2].mul=(st[root*2].mul*st[root].mul)%p;
 49     st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p;
 50     st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p;
 51     st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p;
 52     st[root].mul=1;
 53     st[root].add=0;
 54     return ;
 55 }
 56 void up(int root,int stdl,int stdr,int l,int r,long long k)
 57 {
 58     if(r<stdl||stdr<l)
 59         return ;
 60     if(l<=stdl&&stdr<=r)
 61     {
 62         st[root].v=(st[root].v*k)%p;
 63         st[root].mul=(st[root].mul*k)%p;
 64         st[root].add=(st[root].add*k)%p;
 65         return ;
 66     }
 67     pushdown(root, stdl, stdr);
 68     int m=(stdl+stdr)/2;
 69     up(root*2,stdl,m,l,r,k);
 70     up(root*2+1,m+1,stdr,l,r,k);
 71     st[root].v=(st[root*2].v+st[root*2+1].v)%p;
 72     return ;
 73 }
 74 void date(int root,int stdl,int stdr,int l,int r,long long k)
 75 {
 76     if(r<stdl||stdr<l)
 77         return ;
 78     if(l<=stdl&&stdr<=r)
 79     {
 80         st[root].add=(st[root].add+k)%p;
 81         st[root].v=(st[root].v+k*(stdr-stdl+1))%p;
 82         return ;
 83     }
 84     pushdown(root,stdl,stdr);
 85     int m=(stdl+stdr)/2;
 86     date(root*2,stdl,m,l,r,k);
 87     date(root*2+1,m+1,stdr,l,r,k);
 88     st[root].v=(st[root*2].v+st[root*2+1].v)%p;
 89     return ;
 90 }
 91 long long query(int root,int stdl,int stdr,int l,int r)
 92 {
 93     if(r<stdl||stdr<l)
 94         return 0;
 95     if(l<=stdl&&stdr<=r)
 96         return st[root].v;
 97     pushdown(root,stdl,stdr);
 98     int m=(stdl+stdr)/2;
 99     return (query(root*2,stdl,m,l,r)+query(root*2+1,m+1,stdr,l,r))%p;
100 }
101 int main()
102 {
103     n=read(),m=read(),p=read();
104     for(int i=1; i<=n; i++)
105         a[i]=read();
106     build(1,1,n);
107     while(m--)
108     {
109         judge=read();
110         if(judge==1)
111         {
112             x=read(),y=read(),k=read();
113             up(1,1,n,x,y,k);
114         }
115         else if(judge==2)
116         {
117             x=read(),y=read(),k=read();
118             date(1,1,n,x,y,k);
119         }
120         else
121         {
122             x=read(),y=read();
123             printf("%lld\n", query(1,1,n,x,y));
124         }
125     }
126     return 0;
127 }
View Code

 

posted @ 2018-12-30 10:41  ~liweilin~  阅读(143)  评论(0编辑  收藏  举报