Codeforces 920F-SUM and REPLACE

SUM and REPLACE
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Let D(x) be the number of positive divisors of a positive integer x. For example, D(2) = 2 (2 is divisible by 1 and 2), D(6) = 4 (6 is divisible by 123 and 6).

You are given an array a of n integers. You have to process two types of queries:

  1. REPLACE l r — for every  replace ai with D(ai);
  2. SUM l r — calculate .

Print the answer for each SUM query.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 3·105) — the number of elements in the array and the number of queries to process, respectively.

The second line contains n integers a1a2, ..., an (1 ≤ ai ≤ 106) — the elements of the array.

Then m lines follow, each containing 3 integers tiliri denoting i-th query. If ti = 1, then i-th query is REPLACE li ri, otherwise it's SUM liri (1 ≤ ti ≤ 21 ≤ li ≤ ri ≤ n).

There is at least one SUM query.

Output

For each SUM query print the answer to it.

Example
input
7 6
6 4 1 10 3 2 4
2 1 7
2 4 5
1 3 5
2 4 4
1 5 7
2 1 7
output
30
13
4
22

题意:有n个数,有两种操作,一种是求出l~r的数字和,另一种是将l~r之间的所有数变为它们的因子数

解题思路:线段树,不过若一个区间的最大值小于等于2就没必要更新下去了


#include <iostream>      
#include <cstdio>      
#include <cstring>      
#include <string>      
#include <algorithm>      
#include <map>      
#include <set>      
#include <stack>      
#include <queue>      
#include <vector>      
#include <bitset>      
#include <functional>   

using namespace std;

#define LL long long      
const int INF = 0x3f3f3f3f;

int n, q;
LL x[300009], ma[300009 << 2], sum[300009 << 2];
int p, l, r;
int ans[1000009];

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

void build(int k, int l, int r)
{
	if (l == r)
	{
		scanf("%lld", &x[l]);
		ma[k] = sum[k] = x[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(k << 1, l, mid);
	build(k << 1 | 1, mid + 1, r);
	ma[k] = max(ma[k << 1], ma[k << 1 | 1]);
	sum[k] = sum[k << 1] + sum[k << 1 | 1];
}

void update(int k, int l, int r, int ll, int rr)
{
	if (ma[k] <= 2LL) return;
	if (l == r) { ma[k] = sum[k] = x[l] = ans[x[l]]; return; }
	int mid = (l + r) >> 1;
	if (ll <= mid) update(k << 1, l, mid, ll, rr);
	if (rr > mid) update(k << 1 | 1, mid + 1, r, ll, rr);
	ma[k] = max(ma[k << 1], ma[k << 1 | 1]);
	sum[k] = sum[k << 1] + sum[k << 1 | 1];
}

LL query(int k, int l, int r, int ll, int rr)
{
	if (l >= ll && r <= rr) return sum[k];
	int mid = (l + r) >> 1;
	LL ans = 0;
	if (ll <= mid) ans += query(k << 1, l, mid, ll, rr);
	if (rr > mid) ans += query(k << 1 | 1, mid + 1, r, ll, rr);
	return ans;
}

int main()
{
	init();
	while (~scanf("%d %d", &n, &q))
	{
		build(1, 1, n);
		while (q--)
		{
			scanf("%d %d %d", &p, &l, &r);
			if (p == 1) update(1, 1, n, l, r);
			else printf("%lld\n", query(1, 1, n, l, r));
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值