隐藏
「雅礼day1/CodeForces 438D」求余mod - 线段树 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「雅礼day1/CodeForces 438D」求余mod - 线段树

题目大意

给定一个长度为$n$的非负整数序列$a[]$,你需要支持以下操作:
1:给定 $l$,$r$,输出 $a[l]+a[l+1]+\cdots +a[r]$。
2:给定 $l$,$r$,$x$,将 $a[l],a[l+1],\ldots ,a[r]$对$x$取模。
3:给定 $k$,$y$,将 $a[k]$修改为 $y$。


题目分析

众所周知的结论:一个数有效的取模最多有$\log x$次。

证明:
考虑对于一个数$x$有效地取模$y$,$x\bmod y$的值必然比$y$小,如果$y$小于$\frac x2$,那$x$就变得小于$\frac x2$,如果$y$大于$\frac x2$,$x$剩下的部分也比$\frac x2$少,$x$也会变得比$\frac x2$小。
也就是说,一个数每次取模都会比$\frac x2$小,因此结论成立。

那么只需要对于取模操作暴力取模即可,若区间最大值比模数小就退出。


代码

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
98
99
100
101
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long LL;
inline const LL Get_Int() {
LL num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=100005;
struct Tree {
int left,right;
LL max,sum;
Tree(int l=0,int r=0,LL m=0,LL s=0):left(l),right(r),max(m),sum(s) {}
};
struct Segment_Tree {
Tree tree[maxn*4];
#define ls index<<1
#define rs index<<1|1
void build(int index,int Left,int Right,const LL* a) {
tree[index]=Tree(Left,Right);
if(Left==Right) {
tree[index].sum=tree[index].max=a[Left];
return;
}
int mid=(Left+Right)>>1;
build(ls,Left,mid,a);
build(rs,mid+1,Right,a);
push_up(index);
}
void push_up(int index) {
tree[index].max=max(tree[ls].max,tree[rs].max);
tree[index].sum=tree[ls].sum+tree[rs].sum;
}
void modify(int index,int target,LL val) {
if(tree[index].left>target||tree[index].right<target)return;
if(tree[index].left==tree[index].right) {
tree[index].max=tree[index].sum=val;
return;
}
modify(ls,target,val);
modify(rs,target,val);
push_up(index);
}
void mod(int index,int Left,int Right,LL val) {
if(tree[index].left>Right||tree[index].right<Left)return;
if(tree[index].left==tree[index].right) {
tree[index].max%=val;
tree[index].sum%=val;
return;
}
if(tree[index].max<val)return;
mod(ls,Left,Right,val);
mod(rs,Left,Right,val);
push_up(index);
}
LL query(int index,int Left,int Right) {
if(tree[index].left>Right||tree[index].right<Left)return 0;
if(Left<=tree[index].left&&Right>=tree[index].right)return tree[index].sum;
return query(ls,Left,Right)+query(rs,Left,Right);
}
} st;
int n,m;
LL a[maxn];
int main() {
n=Get_Int();
m=Get_Int();
for(int i=1; i<=n; i++)a[i]=Get_Int();
st.build(1,1,n,a);
for(int i=1; i<=m; i++) {
int opt=Get_Int();
if(opt==1) {
int l=Get_Int(),r=Get_Int();
printf("%lld\n",st.query(1,l,r));
} else if(opt==2) {
int l=Get_Int(),r=Get_Int();
LL v=Get_Int();
st.mod(1,l,r,v);
} else if(opt==3) {
int x=Get_Int();
LL v=Get_Int();
st.modify(1,x,v);
}
}
return 0;
}
姥爷们赏瓶冰阔落吧~