题意:
三种操作:
求
对所有,
思路:
神一般的复杂度分析。。。。记录区间最大值,如果比区间最大值还大,显然不更新,否则暴力更新。因为如果是的话,如果,那么取模之后小于,如果,取模之后也,故每个数取模不会超过次。。。
#include<bits/stdc++.h> typedef long long ll; const int maxn = 1e5 + 10; using namespace std; ll sum[maxn * 4], val[maxn * 4]; void build(int o, int l, int r) { if(l == r) { cin >> sum[o]; val[o] = sum[o]; return ; } int mid = (l + r) >> 1; build(o << 1, l, mid); build(o << 1 | 1, mid + 1, r); val[o] = max(val[o << 1], val[o << 1 | 1]); sum[o] = sum[o << 1] + sum[o << 1 | 1]; } void update_set(int o, int l, int r, int ind, int x) { if(l == r) { val[o] = sum[o] = x; return ; } int mid = (l + r) >> 1; if(ind <= mid) update_set(o << 1, l, mid, ind, x); else update_set(o << 1 | 1, mid + 1, r, ind, x); sum[o] = sum[o << 1] + sum[o << 1 | 1]; val[o] = max(val[o << 1], val[o << 1 | 1]); } void update_mod(int o, int l, int r, int ql, int qr, int mod) { if(l > qr || r < ql) return ; if(l >= ql && r <= qr && val[o] < mod) return ; if(l == r) { sum[o] %= mod; val[o] = sum[o]; return ; } int mid = (l + r) >> 1; int o1 = o << 1, o2 = o1 | 1; update_mod(o1, l, mid, ql, qr, mod); update_mod(o2, mid + 1, r, ql, qr, mod); sum[o] = sum[o1] + sum[o2]; val[o] = max(val[o1], val[o2]); } ll query(int o, int l, int r, int ql, int qr) { if(l > qr || r < ql) return 0; if(l >= ql && r <= qr) return sum[o]; int mid = (l + r) >> 1, o1 = o << 1, o2 = o1 | 1; ll p1 = query(o1, l, mid, ql, qr); ll p2 = query(o2, mid + 1, r, ql, qr); return p1 + p2; } int main() { ios::sync_with_stdio(0); int n, m, T, kase = 1; cin >> n >> m; build(1, 1, n); while(m--) { int op, l, r, x; cin >> op; if(op == 1) { cin >> l >> r; cout << query(1, 1, n, l, r) << endl; } else if(op == 2) { cin >> l >> r >> x; update_mod(1, 1, n, l, r, x); } else { cin >> l >> x; update_set(1, 1, n, l, x); } } return 0; }
文章来源: CodeForces 438D (线段树)