time limit per test : 2 seconds
memory limit per test : 256 megabytes
分数:2000
Let
D
(
x
)
D(x)
D(x) be the number of positive divisors of a positive integer
x
x
x. For example,
D
(
2
)
=
2
D(2) = 2
D(2) = 2 (
2
2
2 is divisible by
1
1
1 and
2
2
2),
D
(
6
)
=
4
D(6) = 4
D(6) = 4 (
6
6
6 is divisible by
1
,
2
,
3
1, 2, 3
1,2,3 and
6
6
6).
You are given an array a of n integers. You have to process two types of queries:
REPLACE l r — for every replace ai with D(ai);
SUM l r — calculate .
Print the answer for each SUM query.
Input
The first line contains two integers n n n and m ( 1 ≤ n , m ≤ 3 ⋅ 1 0 5 ) m (1 ≤ n, m ≤ 3·10^5) 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
a
1
,
a
2
,
.
.
.
,
a
n
(
1
≤
a
i
≤
1
0
6
)
a_1, a_2, ..., a_n (1 ≤ a_i ≤ 10^6)
a1,a2,...,an(1 ≤ ai ≤ 106) — the elements of the array.
Then m lines follow, each containing 3 integers ti, li, ri denoting i-th query. If ti = 1, then i-th query is
R
E
P
L
A
C
E
REPLACE
REPLACE
l
i
l_i
li
r
i
r_i
ri, otherwise it’s
S
U
M
SUM
SUM
l
i
l_i
li
r
i
(
1
≤
t
i
≤
2
,
1
≤
l
i
≤
r
i
≤
n
)
r_i (1 ≤ t_i ≤ 2, 1 ≤ l_i ≤ r_i ≤ n)
ri(1 ≤ ti ≤ 2,1 ≤ 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
题意:
给定一个序列
需要支持两种操作,
第一种操作是将区间i=L~R所有a[i]变为D(a[i]) (D(x)为x的因数个数)
第二种操作是求区间i=L~R所a[i]的和
题解:
线段树经典题
每个点会被改动的次数很少
所以修改的时候只需要暴力修改即可
因为a[i]的最大值只有100w所以可以预处理出所有的D(x)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int D[1000004];
void pre(){
memset(D,0,sizeof(D));
for(int i=1;i<=1000000;i++){
for(int j=i;j<=1000000;j+=i){
D[j]++;
}
}
}
int n,m;
int a[300004];
struct seg{
int l,r;
ll w;
bool tag;
}tr[1200004];
void build(int k,int l,int r){
tr[k].l=l;tr[k].r=r;tr[k].tag=0;
if(l==r){
tr[k].w=a[l];
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
}
void modify(int k,int a,int b){
int l=tr[k].l,r=tr[k].r;
if(tr[k].tag)return ;
if(l==r){
tr[k].w=D[tr[k].w];
if(tr[k].w==D[tr[k].w])tr[k].tag=1;
return ;
}
int mid=(l+r)>>1;
if(b<=mid)modify(k<<1,a,b);
else if(a>mid)modify(k<<1|1,a,b);
else{
modify(k<<1,a,mid);
modify(k<<1|1,mid+1,b);
}
tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
tr[k].tag=(tr[k<<1].tag&&tr[k<<1|1].tag);
}
ll query(int k,int a,int b){
int l=tr[k].l,r=tr[k].r;
if(l==a&&r==b)return tr[k].w;
int mid=(l+r)>>1;
if(b<=mid)return query(k<<1,a,b);
else if(a>mid)return query(k<<1|1,a,b);
else {
return query(k<<1,a,mid)+query(k<<1|1,mid+1,b);
}
}
int main(){
pre();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,1,n);
while(m--){
int t,l,r;
scanf("%d%d%d",&t,&l,&r);
if(t==1){
modify(1,l,r);
}
if(t==2){
printf("%lld\n",query(1,l,r));
}
}
return 0;
}