P3373 【模板】线段树 2

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)

分析

线段树维护两个标记,add,mul表示要加的数,和要乘的数。

下传标记时,add也是要乘以mul的。

还有要开longlong qaq

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<vector>
 4 #define lson l,m,rt<<1
 5 #define rson m+1,r,rt<<1|1
 6 #define LL long long
 7 
 8 using namespace std;
 9 const int N = 500100;
10 LL sum[N],mul[N],add[N];
11 LL n,m,p;
12 
13 inline char nc() {
14     static char buf[100000],*p1,*p2;
15     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
16 }
17 inline LL read() {
18     LL x = 0,f = 1;char ch = nc();
19     for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f=-1;
20     for (; ch>='0'&&ch<='9'; ch = nc()) x = x*10+ch-'0';
21     return x * f;
22 }
23 void pushup(int rt) {
24     sum[rt] = (sum[rt<<1] + sum[rt<<1|1]) % p;
25 }
26 void pushdown(int rt,int k) {
27     sum[rt<<1] = (sum[rt<<1]*mul[rt]+add[rt]*(k-k/2))%p;
28     sum[rt<<1|1] = (sum[rt<<1|1]*mul[rt]+add[rt]*(k/2))%p;
29     mul[rt<<1] = (mul[rt<<1]*mul[rt])%p;
30     mul[rt<<1|1] = (mul[rt<<1|1]*mul[rt])%p;
31     add[rt<<1] = (add[rt<<1]*mul[rt]+add[rt])%p;
32     add[rt<<1|1] = (add[rt<<1|1]*mul[rt]+add[rt])%p;
33     mul[rt] = 1;add[rt] = 0;
34 }
35 void build(int l,int r,int rt) {
36     mul[rt] = 1,add[rt] = 0;
37     if (l==r) {
38         sum[rt] = read();return ;
39     }
40     int m = (l + r) / 2;
41     build(lson);
42     build(rson);
43     pushup(rt);
44 }
45 void update(int l,int r,int rt,int L,int R,int x,int tp) {
46     if (L <= l && r <= R) {
47         if (tp==0) add[rt] = (add[rt]+x)%p,sum[rt] = (sum[rt]+(r-l+1)*x)%p;
48         else mul[rt]=(mul[rt]*x)%p,add[rt]=(add[rt]*x)%p,sum[rt]=(sum[rt]*x)%p;
49         return ;
50     }
51     pushdown(rt,r-l+1);
52     int m = (l + r) / 2;
53     if (L <= m) update(lson,L,R,x,tp);
54     if (R > m)  update(rson,L,R,x,tp);
55     pushup(rt);    
56 }
57 LL query(int l,int r,int rt,int L,int R) {
58     if (L <= l && r <= R) {
59         return sum[rt] % p;
60     }
61     pushdown(rt,r-l+1);
62     int m = (l + r) / 2;
63     LL ret = 0;
64     if (L <= m) ret = (ret + query(lson,L,R)) % p;
65     if (R > m)  ret = (ret + query(rson,L,R)) % p;
66     return ret % p;
67 }
68 int main () {
69     n = read(),m = read(),p = read();
70     build(1,n,1);
71     while (m--) {
72         int opt = read();
73         if (opt==1) {
74             int a = read(),b = read(),c = read();
75             update(1,n,1,a,b,c,1);
76         } else if (opt==2) {
77             int a = read(),b = read(),c = read();
78             update(1,n,1,a,b,c,0);
79         } else {
80             int a = read(),b = read();
81             printf("%lld
",(query(1,n,1,a,b) + p)%p);
82         }
83     }
84     return 0;
85 }
View Code
原文地址:https://www.cnblogs.com/mjtcn/p/8438008.html