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
时间: 2024-11-11 03:36:41