CF920F SUM and REPLACE
和模板的不同之处在于修改时是改为每个数的约数个数,不难发现,当一个数x<=2时,x的约数个数与本身相等,修改多少次多不会在改变
先预处理出每个数的约数个数,用线段树维护区间最大值,若<=2,则直接结束递归
对于>2的数都要暴力修改,但由于每个数的约数个数下降很快,几次后便降到<=2,所以复杂度优秀(大约是nlogn?)
这题与CF438D The Child and Sequence(区间取模),类似,也可以维护区间最大值
CF920F:
#include <bits/stdc++.h> using namespace std; #define rg register #define ll long long inline void read (int &x) { char ch = getchar(); x = 0; while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar(); } void print (ll x) { if (x > 9) print (x / 10); putchar (x % 10 + 48); } const int N = 3e5 + 10, M = 1e6; int n, m, opt, ql, qr, cnt, maxn, p[N], a[N], k[M + 10], num[M + 10], c[N << 2]; ll s[N << 2]; inline void pre_work () { num[1] = 1; for (rg int i = 2; i <= maxn; ++i) { if (!k[i]) p[++cnt] = i, num[i] = 2; for (rg int j = 1; j <= cnt && p[j] * i <= maxn; ++j) { int tmp (p[j] * i), t (0); while (tmp % p[j] == 0) ++t, tmp /= p[j]; k[p[j] * i] = 1, num[p[j] * i] = num[tmp] * (t + 1); if (i % p[j] == 0) continue; } } } #define ls p << 1 #define rs p << 1 | 1 inline int Max (int a, int b) {return a > b ? a : b;} inline void push_up (int p) { s[p] = s[ls] + s[rs], c[p] = Max (c[ls], c[rs]); } void build (int p, int l, int r) { if (l == r) {c[p] = s[p] = a[l]; return;} int mid = l + r >> 1; build (ls, l, mid), build (rs, mid + 1, r); push_up (p); } void update (int p, int l, int r) { if (c[p] <= 2) return; if (l == r) {c[p] = s[p] = num[c[p]]; return;} int mid = l + r >> 1; if (ql <= mid) update (ls, l, mid); if (qr > mid) update (rs, mid + 1, r); push_up (p); } ll ask (int p, int l, int r) { if (ql <= l and qr >= r) return s[p]; ll s (0); int mid = l + r >> 1; if (ql <= mid) s += ask (ls, l, mid); if (qr > mid) s += ask (rs, mid + 1, r); return s; } int main() { read (n), read (m); for (rg int i = 1; i <= n; ++i) read (a[i]), maxn = Max (maxn, a[i]); pre_work (), build (1, 1, n); for (rg int i = 1; i <= m; ++i) { read (opt); if (opt == 1) read (ql), read (qr), update (1, 1, n); else read (ql), read (qr), print (ask (1, 1, n)), puts (""); } return 0; }
CF438D:
#include <bits/stdc++.h> using namespace std; #define rg register #define ll long long inline void read (int &x) { char ch = getchar(); x = 0; while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar(); } void print (ll x) { if (x > 9) print (x / 10); putchar (x % 10 + 48); } const int N = 1e5 + 10; int n, m, opt, ql, qr, mod, val, pos, a[N], c[N << 2]; ll s[N << 2]; #define ls p << 1 #define rs p << 1 | 1 inline int Max (int a, int b) {return a > b ? a : b;} inline void push_up (int p) { s[p] = s[ls] + s[rs], c[p] = Max (c[ls], c[rs]); } void build (int p, int l, int r) { if (l == r) {c[p] = s[p] = a[l]; return;} int mid = l + r >> 1; build (ls, l, mid), build (rs, mid + 1, r); push_up (p); } void update (int p, int l, int r) { if (c[p] < mod) return; if (l == r) {c[p] %= mod, s[p] %= mod; return;} int mid = l + r >> 1; if (ql <= mid) update (ls, l, mid); if (qr > mid) update (rs, mid + 1, r); push_up (p); } void change (int p, int l, int r) { if (l == r) {c[p] = s[p] = val; return;} int mid = l + r >> 1; (pos <= mid) ? change (ls, l, mid) : change (rs, mid + 1, r); push_up (p); } ll ask (int p, int l, int r) { if (ql <= l and qr >= r) return s[p]; ll s (0); int mid = l + r >> 1; if (ql <= mid) s += ask (ls, l, mid); if (qr > mid) s += ask (rs, mid + 1, r); return s; } int main() { read (n), read (m); for (rg int i = 1; i <= n; ++i) read (a[i]); build (1, 1, n); for (rg int i = 1; i <= m; ++i) { read (opt); if (opt == 1) { read (ql), read (qr); print (ask (1, 1, n)), puts (""); } else if (opt == 2) { read (ql), read (qr), read (mod); update (1, 1, n); } else { read (pos), read (val); change (1, 1, n); } } return 0; }
来源:https://www.cnblogs.com/whx666/p/12041522.html