【luogu 3373】【模板】线段树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)

(模板题敲bi半天,结果在局部变量挂了,QAQ)

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define maxn 100005
 6 #define LL long long
 7 #define ll l,mid,rt<<1
 8 #define rr mid+1,r,rt<<1|1
 9 using namespace std;
10 LL n,m,Mod,a[maxn],add[maxn<<2],mul[maxn<<2],sum[maxn<<2];
11 LL read(){
12     LL x=0,f=1;char ch=getchar();
13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 void build(LL l,LL r,LL rt){
18     mul[rt]=1;add[rt]=0;
19     if(l==r){
20         sum[rt]=a[l];
21         return ;
22     }
23     LL mid=(l+r)>>1;
24     build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);
25     sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%Mod;
26 }
27 void pushdown(LL rt,LL k){
28     sum[rt<<1]=(sum[rt<<1]*mul[rt]+add[rt]*(k-(k>>1)))%Mod;
29     sum[rt<<1|1]=(sum[rt<<1|1]*mul[rt]+add[rt]*(k>>1))%Mod;
30     mul[rt<<1]=(mul[rt<<1]*mul[rt])%Mod;
31     mul[rt<<1|1]=(mul[rt<<1|1]*mul[rt])%Mod;
32     add[rt<<1]=(add[rt<<1]*mul[rt]+add[rt])%Mod;
33     add[rt<<1|1]=(add[rt<<1|1]*mul[rt]+add[rt])%Mod;
34     mul[rt]=1;add[rt]=0;
35 }
36 void Add(LL ql,LL qr,LL v,LL l,LL r,LL rt){
37     if(ql<=l&&r<=qr){
38         add[rt]=(add[rt]+v)%Mod;
39         sum[rt]=(sum[rt]+v*(r-l+1))%Mod;
40         return ;
41     }
42     pushdown(rt,r-l+1);
43     LL mid=(l+r)>>1;
44     if(ql<=mid) Add(ql,qr,v,ll);
45     if(mid<qr) Add(ql,qr,v,rr);
46     sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%Mod;
47 }
48 void Mul(LL ql,LL qr,LL v,LL l,LL r,LL rt){
49     if(ql<=l&&r<=qr){
50         add[rt]=(add[rt]*v)%Mod;
51         mul[rt]=(mul[rt]*v)%Mod;
52         sum[rt]=(sum[rt]*v)%Mod;
53         return ;
54     }
55     pushdown(rt,r-l+1);
56     LL mid=(l+r)>>1;
57     if(ql<=mid) Mul(ql,qr,v,ll);
58     if(mid<qr) Mul(ql,qr,v,rr);
59     sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%Mod;
60 }
61 LL query(LL ql,LL qr,LL l,LL r,LL rt){
62     if(ql<=l&&r<=qr) return sum[rt]%Mod;
63     LL mid=(l+r)>>1;
64     pushdown(rt,r-l+1);
65     LL tmp=0;
66     if(ql<=mid) tmp=(tmp+query(ql,qr,ll))%Mod;
67     if(mid<qr) tmp=(tmp+query(ql,qr,rr))%Mod;
68     sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%Mod;
69     return tmp%Mod;
70 }
71 int main(){
72     n=read(),m=read(),Mod=read();
73     for(int i=1;i<=n;i++) a[i]=read();
74     build(1,n,1);
75     for(int i=1;i<=m;i++){
76         LL Q=read();
77         if(Q==1){
78             LL x=read(),y=read(),z=read();
79             Mul(x,y,z,1,n,1);
80         }
81         if(Q==2){
82             LL x=read(),y=read(),z=read();
83             Add(x,y,z,1,n,1);
84         }
85         if(Q==3){
86             LL x=read(),y=read();
87             printf("%lld\n",query(x,y,1,n,1)%Mod);
88         }
89     }
90     return 0;
91 }
posted @ 2017-10-14 22:18  Emine  阅读(176)  评论(0编辑  收藏  举报