題意:c++
給定一個長度爲n的非負整數序列a,你須要支持如下操做:
1)給定l,r,輸出a[l] + a[l+1] + ... + a[r]git
2)給定l,r,x, 將a[l]、a[l+1]、....、a[r]對x取模ui
3)給定k,y,將a[k]修改成yspa
n, m <= 100000,a[i], x, y <= 109code
對於操做(1)(3)很是簡單,線段樹基本操做blog
問題是操做(2),顯然的是咱們不能對區間和取模,這樣就很難受get
可是咱們能夠想到,一個數如果比模數小,就不須要取模,而一個數w有效取模次數最多爲log(w)it
同時單個數被有效取模的一次只會花費O(logn)class
所以每次修改至多使複雜度增長O(lognlogw)date
這樣咱們對於區間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 }