CodeForces 920F SUM and REPLACE (线段树)
F. SUM and REPLACE
memory limit per test: 256 megabytes
input: standard input
output: standard output
Description
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 1, 2, 3 and 6).
You are given an array a of n integers. You have to process two types of queries:
- REPLACE l r — for every replace a**i with D(a**i);
- 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 a1, a2, …, a**n (1 ≤ a**i ≤ 106) — the elements of the array.
Then m lines follow, each containing 3 integers t**i, l**i, r**i denoting i-th query. If t**i = 1, then i-th query is REPLACE l**i r**i, otherwise it’s SUM lir**i (1 ≤ t**i ≤ 2, 1 ≤ l**i ≤ r**i ≤ n).
There is at least one SUM query.
Output
For each SUM query print the answer to it.
Example
input
1 | 7 6 |
output
1 | 30 |
Solution
题意
数组区间求和,区间更新为将 $a [i]$ 变为 $a [i]$ 的 因子个数。
思路
明显的线段树。
首先要暴力预处理出 $[1, 10^6]$ 每个数因子的个数。发现数字 1 的因子数为 1,2 的因子数为 2, 故 $num \le 2$ 时,不再会更新值。
这个题较坑的一点是会卡常数,我用 scanf()
输入会在 Case2 T 掉,而改用读入挂后只用了 249ms。
AC 代码
1 |
|
41131343 | 2018-08-02 20:37:41 | MoonChasing | F - SUM and REPLACE | GNU C++ | Accepted | 249 ms | 54800 KB |
---|---|---|---|---|---|---|---|
41131149 | 2018-08-02 20:30:15 | MoonChasing | F - SUM and REPLACE | GNU C++ | Time limit exceeded on test 2 | 2000 ms | 54800 KB |
41130678 | 2018-08-02 20:10:48 | MoonChasing | F - SUM and REPLACE | GNU C++ | Time limit exceeded on test 2 | 2000 ms | 54800 KB |
总结
第一次遇到卡常的题目,被读入挂惊呆了。没想到读入挂这么厉害。
更新:
这题自己会 T 并不是因为卡读入,而是因为一开始自己写的程序中,叶子结点时写的是 l[::a]
,可能是因为::a 双冒号访问会慢。将其改成 sum[root]
会可以 AC。