Luogu P3373 模板线段树 2

Posted gE_nis

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu 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

 1 //2018年2月22日21:51:08
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 int n, m, mo;
 9 int A[410000], B[410000], sum[410000], size[410000];
10 
11 void change(int k1){
12     sum[k1] = (sum[k1*2]+sum[k1*2+1]) % mo;
13 }
14 
15 void buildtree(int k1, int l, int r){
16     size[k1] = r-l+1; B[k1] = 1;
17     if(l == r){
18         scanf("%d", &sum[k1]); return;
19     }
20     int mid = (l+r) >> 1;
21     buildtree(k1*2, l, mid);
22     buildtree(k1*2+1, mid+1, r);
23     change(k1); 
24 }
25 
26 void add(int k1, int x){
27     A[k1] = (A[k1]+x) % mo;
28     sum[k1] = (sum[k1]+1ll*size[k1]*x) % mo;
29 }
30 
31 void chen(int k1, int x){
32     A[k1] = 1ll*A[k1]*x % mo;
33     B[k1] = 1ll*B[k1]*x % mo;
34     sum[k1] = 1ll * sum[k1]*x % mo;
35 }
36 
37 void pushdown(int k1){
38     if(B[k1] != 1){
39         chen(k1*2, B[k1]);
40         chen(k1*2+1, B[k1]); B[k1] = 1; 
41     }
42     if(A[k1]){
43         add(k1*2, A[k1]);
44         add(k1*2+1, A[k1]);
45         A[k1] = 0;
46     }
47 }
48 
49 void add(int k1, int l, int r, int L, int R, int x){
50     if(l>R || r<L) return;
51     if(l>=L && r<=R){
52         add(k1, x);
53         return;
54     }
55     int mid = (l+r) >> 1;
56     pushdown(k1);
57     add(k1*2, l, mid, L, R, x);
58     add(k1*2+1, mid+1, r, L, R, x);
59     change(k1);
60 }
61 
62 void chen(int k1, int l, int r, int L, int R, int x){
63     if(l>R || r<L) return;
64     if(l>=L && r<=R){
65         chen(k1, x); return;
66     }
67     int mid = l+r >> 1;
68     pushdown(k1);
69     chen(k1*2, l, mid, L, R, x);
70     chen(k1*2+1, mid+1, r, L, R, x);
71     change(k1);
72 }
73 
74 int find(int k1, int l, int r, int L, int R){
75     if(l>R || r<L) return 0;
76     if(l>=L && r<=R) return sum[k1];
77     int mid = l+r >> 1;
78     pushdown(k1);
79     return (find(k1*2,l,mid,L,R) + find(k1*2+1,mid+1,r,L,R) ) % mo;
80 }
81 
82 int main(){
83     scanf("%d%d%d", &n, &m, &mo);
84     buildtree(1, 1, n);
85     for(; m; m--){
86         int k1, k2, k3;
87         scanf("%d%d%d", &k1, &k2, &k3);
88         if(k1 == 2){
89             int k4; scanf("%d", &k4); add(1, 1, n, k2, k3, k4);
90         }else if(k1 == 1){
91             int k4; scanf("%d", &k4); chen(1, 1, n, k2, k3, k4);
92         }else printf("%d\n", find(1, 1, n, k2, k3));
93     }
94 
95     return 0;
96 }

 

以上是关于Luogu P3373 模板线段树 2的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3373 模板线段树 2

原创洛谷 LUOGU P3373 模板线段树2

luogu P3373 模板线段树 2

Luogu P3373 模板线段树 2

P3373 模板线段树 2区间乘/加 区间查询

P3373 模板线段树 2 (未完待续)