-线段树- [洛谷 P2023][AHOI2009]维护序列

题目描述

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。

有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

输入格式

第一行两个整数N和P(1≤P≤1000000000)。 第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。 第三行有一个整数M,表示操作总数。 从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

输出格式

对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

输入样例

7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

输出样例

2
35
8

说明

【样例说明】

初始时数列为(1,2,3,4,5,6,7)。

经过第1次操作后,数列为(1,10,15,20,25,6,7)。

对第2次操作,和为10+15+20=45,模43的结果是2。

经过第3次操作后,数列为(1,10,24,29,34,15,16}

对第4次操作,和为1+10+24=35,模43的结果是35。

对第5次操作,和为29+34+15+16=94,模43的结果是8。

测试数据规模如下表所示

数据编号 1 2 3 4 5 6 7 8 9 10

N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

Solution

这道题读一遍就知道是线段树模板题,所以不多说,直接上代码

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls(x) ((x)<<1)
#define rs(x) (((x)<<1)|(1))
#define MAXN 1000100
#define LL long long
using namespace std;
LL mod;
struct Segment_Tree {
LL sum[MAXN<<2],add[MAXN<<2],mul[MAXN<<2];
void p_u(int rt) {
sum[rt]=sum[ls(rt)]+sum[rs(rt)];
}
void p_d(LL rt,LL len) {
if(add[rt]!=0||mul[rt]!=1) {
add[ls(rt)]=((add[ls(rt)]%mod)*(mul[rt]%mod)+add[rt])%mod;
add[rs(rt)]=((add[rs(rt)]%mod)*(mul[rt]%mod)+add[rt])%mod;
/*********************************************************************************************/
mul[ls(rt)]=(mul[rt<<1]*mul[rt])%mod;
mul[rs(rt)]=(mul[rs(rt)]*mul[rt])%mod;
/*********************************************************************************************/
sum[ls(rt)]=((add[rt]%mod)*(len-(len>>1))%mod+(sum[ls(rt)]%mod)*mul[rt]%mod)%mod;
sum[rs(rt)]=(((add[rt]%mod)*(len>>1))%mod+(sum[rs(rt)]%mod)*mul[rt]%mod)%mod;
/*********************************************************************************************/
add[rt]=0;
mul[rt]=1;
}
}
void build(LL l,LL r,LL rt) {
add[rt]=0;
mul[rt]=1;
if(l==r) {
scanf("%lld",&sum[rt]);
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
p_u(rt);
}
void update1(LL L,LL R,LL c,LL l,LL r,LL rt) {
if(L<=l&&r<=R) {
add[rt]=add[rt]*c%mod;
mul[rt]=mul[rt]*c%mod;
sum[rt]=sum[rt]*c%mod;
return ;
}
p_d(rt,r-l+1);
LL m=(l+r)>>1;
if(L<=m) update1(L,R,c,lson);
if(m<R) update1(L,R,c,rson);
p_u(rt);
}
void update2(LL L,LL R,LL c,LL l,LL r,LL rt) {
if(L<=l&&r<=R) {
add[rt]=(add[rt]+c)%mod;
sum[rt]=(sum[rt]+(r-l+1)*c)%mod;
return ;
}
p_d(rt,r-l+1);
LL m=(l+r)>>1;
if(L<=m) update2(L,R,c,lson);
if(m<R) update2(L,R,c,rson);
p_u(rt);
}
LL query(LL L,LL R,LL l,LL r,LL rt) {
if(L<=l&&r<=R) return sum[rt]%mod;
p_d(rt,r-l+1);
LL ret=0;
int m=(l+r)>>1;
if(L<=m)ret+=query(L,R,lson)%mod;
if(R>m) ret+=query(L,R,rson)%mod;
return ret%mod;
}
}Tree;
int main() {
LL n,m;
scanf("%lld%lld",&n,&mod);
Tree.build(1,n,1);
LL op,a,b,c;
scanf("%lld",&m);
while(m--) {
scanf("%lld",&op);
if(op==1) {
scanf("%lld%lld%lld",&a,&b,&c);
Tree.update1(a,b,c,1,n,1);
} else if(op==2) {
scanf("%lld%lld%lld",&a,&b,&c);
Tree.update2(a,b,c,1,n,1);
} else {
scanf("%lld%lld",&a,&b);
printf("%lld\n",Tree.query(a,b,1,n,1)%mod);
}
}
return 0;
}
文章作者: RiverFun
文章链接: https://stevebraveman.github.io/blog/2018/08/28/27/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 RiverFun

评论