W
H
X

CF920F SUM and REPLACE 题解

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;
}
posted @ 2019-12-14 23:31  -敲键盘的猫-  阅读(199)  评论(0编辑  收藏  举报