标签:tin cstring print 复杂度 而且 线段树 约数 main line
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:
$ 1. REPLACE \quad l \quad r $ —— for every $ i \in [l,r] $ replace $ a_i $ with $ D(a_i) $ ;
$ 2. SUM \quad l \quad r $ —— calculate $ \sum_{i=l}^r a_i $ .
Print the answer for each $ SUM $ query.
The first line contains two integers $ n $ and $ m (1?≤?n,?m?≤?3·10^5) $
— 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?≤?ai?≤?10^6) $ — the elements of the array.
Then $ m $ lines follow, each containing $ 3 $ integers $ t_i, l_i, r_i $ denoting $ i $ -th query.
If $ ti?=?1 $ , then $ i $ -th query is $ REPLACE \quad l_i \quad r_i $ , otherwise it‘s $ SUM \quad l_i \quad r_i (1?≤?t_i?≤?2, 1?≤?l_i?≤?r_i?≤?n) $ .
There is at least one $ SUM $ query.
For each $ SUM $ query print the answer to it.
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
30
13
4
22
给你 $ n $ 个数,进行 $ m $ 次操作,分别是将区间 $ [l,r] $ 内的所有数替换成自己的因子数 和 对区间 $ [l,r] $ 进行求和。
数据范围: $ 1 \le n,m \le 3 \times 10^5 $
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXM 1000005
#define N 300005
#define int long long
int n,m,M;
int d[MAXM],c[MAXM],p[MAXM];
bool vis[MAXM];
void pre(){
d[1]=1;
for(int i=2;i<=M;++i){
if(!vis[i]){ p[++p[0]]=i; vis[i]=1; d[i]=2; c[i]=1; }
for(int j=1;j<=p[0]&&1ll*i*p[j]<=M;++j){
vis[i*p[j]]=1;
if(i%p[j]==0){
d[i*p[j]]=d[i]/(c[i]+1)*(c[i]+2);
c[i*p[j]]=c[i]+1;
break;
}
d[i*p[j]]=d[i]*2;
c[i*p[j]]=1;
}
}
}
int sum[N<<2];
bool flag[N<<2];
void build(int o,int l,int r){
if(l==r){
scanf("%lld",&sum[o]);
if(sum[o]==1||sum[o]==2) flag[o]=1;
M=max(M,sum[o]);
return;
}
int mid=l+r>>1;
build(o<<1,l,mid); build(o<<1|1,mid+1,r);
sum[o]=sum[o<<1]+sum[o<<1|1];
flag[o]=flag[o<<1]&flag[o<<1|1];
}
void updata(int o,int l,int r,int L,int R){
if(flag[o]) return;
if(l==r&&L<=l&&l<=R){
sum[o]=d[sum[o]];
if(sum[o]==1||sum[o]==2) flag[o]=1;
return;
}
int mid=l+r>>1;
if(L>mid) updata(o<<1|1,mid+1,r,L,R);
else if(R<=mid) updata(o<<1,l,mid,L,R);
else {
updata(o<<1,l,mid,L,R);
updata(o<<1|1,mid+1,r,L,R);
}
sum[o]=sum[o<<1]+sum[o<<1|1];
flag[o]=flag[o<<1]&flag[o<<1|1];
}
int query(int o,int l,int r,int L,int R){
if(L<=l&&r<=R) return sum[o];
int mid=l+r>>1;
if(L>mid) return query(o<<1|1,mid+1,r,L,R);
else if(R<=mid) return query(o<<1,l,mid,L,R);
else return query(o<<1,l,mid,L,R)+query(o<<1|1,mid+1,r,L,R);
}
signed main(){
scanf("%lld %lld",&n,&m);
build(1,1,n);
pre();
while(m--){
int opt,x,y;
scanf("%lld %lld %lld",&opt,&x,&y);
if(opt==1) updata(1,1,n,x,y);
else printf("%lld\n",query(1,1,n,x,y));
}
return 0;
}
/*
# 42607112
When 2018-09-07 11:38:57
Who PotremZ
Problem F - SUM and REPLACE
Lang GNU C++11
Verdict Accepted
Time 467 ms
Memory 35000 KB
*/
codeforces CF920F SUM and REPLACE 线段树 线性筛约数
标签:tin cstring print 复杂度 而且 线段树 约数 main line
原文地址:https://www.cnblogs.com/PotremZ/p/9606942.html