CF438 The Child and Sequence
题意:
给定一个长度为n的非负整数序列a,你需要支持以下操作:
1)给定l,r,输出a[l] + a[l+1] + ... + a[r]
2)给定l,r,x, 将a[l]、a[l+1]、....、a[r]对x取模
3)给定k,y,将a[k]修改为y
n, m <= 100000,a[i], x, y <= 109
对于操作(1)(3)非常简单,线段树基本操作
问题是操作(2),显然的是我们不能对区间和取模,这样就很难受
但是我们可以想到,一个数若是比模数小,就不需要取模,而一个数w有效取模次数最多为log(w)
同时单个数被有效取模的一次只会花费O(logn)
因此每次修改至多使复杂度增加O(lognlogw)
这样我们对于区间l, r暴力对每个能取模的数取模即可
最后时间复杂度为O(mlognlogw)
1 #include<bits/stdc++.h>
2 #define ll long long
3 #define uint unsigned int
4 #define ull unsigned long long
5 using namespace std;
6 const int maxn = 100010;
7 struct shiki {
8 ll maxx, sum;
9 }tree[maxn << 2];
10 int n, m;
11 ll a[maxn];
12
13 inline ll read() {
14 ll x = 0, y = 1;
15 char ch = getchar();
16 while(!isdigit(ch)) {
17 if(ch == '-') y = -1;
18 ch = getchar();
19 }
20 while(isdigit(ch)) {
21 x = (x << 1) + (x << 3) + ch - '0';
22 ch = getchar();
23 }
24 return x * y;
25 }
26
27 inline void maintain(int pos) {
28 int ls = pos << 1, rs = pos << 1 | 1;
29 tree[pos].maxx = max(tree[ls].maxx, tree[rs].maxx);
30 tree[pos].sum = tree[ls].sum + tree[rs].sum;
31 }
32
33 void build(int pos, int l, int r) {
34 if(l == r) {
35 tree[pos].maxx = tree[pos].sum = a[l];
36 return;
37 }
38 int mid = l + r >> 1;
39 build(pos << 1, l, mid);
40 build(pos << 1 | 1, mid + 1, r);
41 maintain(pos);
42 }
43
44 void get_mod(int pos, int L, int R, int l, int r, ll mod) {
45 if(l > R || r < L) return;
46 if(tree[pos].maxx < mod) return;
47 if(l == r) {
48 tree[pos].sum %= mod;
49 tree[pos].maxx %= mod;
50 return;
51 }
52 int mid = l + r >> 1;
53 get_mod(pos << 1, L, R, l, mid, mod);
54 get_mod(pos << 1 | 1, L, R, mid + 1, r, mod);
55 maintain(pos);
56 }
57
58 void update(int pos, int aim, int l, int r, ll val) {
59 if(l == r && l == aim) {
60 tree[pos].maxx = tree[pos].sum = val;
61 return;
62 }
63 int mid = l + r >> 1;
64 if(aim <= mid) update(pos << 1, aim, l, mid, val);
65 else update(pos << 1 | 1, aim, mid + 1, r, val);
66 maintain(pos);
67 }
68
69 ll query_sum(int pos, int L, int R, int l, int r) {
70 if(l > R || r < L) return 0;
71 if(l >= L & r <= R) return tree[pos].sum;
72 int mid = l + r >> 1;
73 return query_sum(pos << 1, L, R, l, mid) + query_sum(pos << 1 | 1, L, R, mid + 1, r);
74 }
75
76 int main() {
77 n = read(), m = read();
78 for(int i = 1; i <= n; ++i) a[i] = read();
79 build(1, 1, n);
80 for(int i = 1; i <= m; ++i) {
81 int opt = read(), x = read(), y = read();
82 if(opt == 1) printf("%I64d\n", query_sum(1, x, y, 1, n));
83 if(opt == 2) {
84 ll p = read();
85 get_mod(1, x, y, 1, n, p);
86 }
87 if(opt == 3) update(1, x, 1, n, y);
88 }
89 return 0;
90 }