CF920F SUM and REPLACE

题面

题意:

给定 \(n\) 个数的数组 \(a\)\(m\) 次操作。操作有两种:

  1. \(i\in[l,r]\) 中的所有 \(a_i\) 替换为 \(d(a_i)\)\(d(x)\) 表示 \(x\) 的正约数的个数。
  2. \(\displaystyle\sum_{i=l}^r a_i\)

首先\(d\)是可以预处理出来的qwq。比如通过线性筛。

线性筛太麻烦了有这样一种预处理方式:

for(int i = 1; i <= 1000000; i ++){
	for(int j = i; j <= 1000000; j += i){
		d[j] ++;
	}
}

实践证明它是不会T的。

然后我们通过观察显然可以发现,在进行好多次操作之后,每个数会一直是\(1\)\(2\)

所以对于一个数我们直接暴力修改。毕竟最多的修改次数不会超过\(6\)次。

在维护区间和的同时维护一个区间最大值。

当修改过程中某个区间最大值小于等于\(2\)的时候,说明我们这次的操作是无能的无效的,直接返回即可。

注意要开long long,不然会爆掉orz。所以直接define int long long

时间复杂度\(O(mlogn)\)

代码:

#include <bits/stdc++.h>
#define ls (now << 1)
#define rs (now<<1|1)
#define mid ((l+r)>>1)
#define int long long
using namespace std;

const int maxn = 3e5+10;

int n, m, a[maxn], d[1000010];

struct seg_tree{
	struct nodes{
		int l, r, sum, max_num;
	}node[maxn<<2];
	void up(int now){return (void)(node[now].sum = node[ls].sum + node[rs].sum, node[now].max_num = max(node[ls].max_num, node[rs].max_num));}
	void build(int l, int r, int now){
		node[now].l = l, node[now].r = r;
		if(l == r) return (void)(node[now].sum = a[l], node[now].max_num = a[l]);
		build(l, mid, ls), build(mid+1, r, rs);
		return up(now);
	}
	void chenge(int l, int r, int now){
		if(r < node[now].l or node[now].r < l or node[now].max_num <= 2) return;
		if(node[now].l == node[now].r) return(void) (node[now].max_num = node[now].sum = d[node[now].sum]);
		chenge(l, r, ls), chenge(l, r, rs);
		return up(now);
	}
	void quary(int l, int r, int now, int &ans){
		if(r < node[now].l or node[now].r < l) return;
		if(l <= node[now].l and node[now].r <= r) return (void)(ans += node[now].sum);
		quary(l, r, ls, ans), quary(l, r, rs, ans);
		return up(now);
	}
}tree;

signed main(){
	for(int i = 1; i <= 1000000; i ++){
		for(int j = i; j <= 1000000; j += i){
			d[j] ++;
		}
	}
	scanf("%lld%lld", &n, &m);
	for(int i = 1; i <= n; i ++) scanf("%lld", &a[i]);
	tree.build(1, n, 1);
	for(int i = 1, x, y, z; i <= m; i ++){
		scanf("%lld%lld%lld", &x, &y, &z);
		if(x&1) tree.chenge(y, z, 1);
		else{
			int ans = 0;
			tree.quary(y, z, 1, ans);
			printf("%lld\n", ans);
		}
	}
	return 0;
}
posted @ 2020-09-16 15:29  Vanyun  阅读(90)  评论(0编辑  收藏  举报