920 F. SUM and REPLACE 线段树 或 树状数组+并查集
F. SUM and REPLACE
题意:
给你n个数,按照顺序排列,再进行m次操作。每次操作要么是问你区间[l,r]的和,要么是让你将区间[l,r]的所有数进行操作:\(a_i=D(a_i),D(i)=i的因子数\),如:\(D(2)=2 (因子:1,2),D(6)=4 (因子:1,2,3,6)\)
思路:
做法一:线段树维护区间最大值和区间和
详见链接2023ACM暑假训练day 8 线段树-J题
做法二:树状数组+并查集
单点修改区间查询树状数组+并查集优化区间查询,非常好的结合方式
利用并查集将区间修改优化,去掉无用的单点修改
//>>>Qiansui
#include<map>
#include<set>
#include<list>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<string>
#include<vector>
#include<utility>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<functional>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
#define debug(x) cout << #x << " = " << x << endl
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << endl
//#define int long long
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ull,ull> pull;
typedef pair<double,double> pdd;
/*
树状数组+并查集
*/
const int maxm=3e5+5,maxn=1e6+5,inf=0x3f3f3f3f,mod=998244353;
ll n,m,c[maxm],d[maxn],fa[maxn],a[maxm];
void pre(){
for(int i=1;i<=maxn;++i){
for(int j=i;j<=maxn;j+=i){
++d[j];
}
fa[i]=i;
}
return ;
}
int findfa(int x){ return fa[x]==x?x:fa[x]=findfa(fa[x]);}
int lowbit(int x){ return x&(-x); }
void update(int x,ll v){
while(x<=n){
c[x]+=v;
x+=lowbit(x);
}
return ;
}
ll getsum(int x){
ll ans=0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
void solve(){
pre();
cin>>n>>m;
ll t;
for(int i=1;i<=n;++i){
cin>>a[i];
update(i,a[i]);
}
ll c,x,y;
while(m--){
cin>>c>>x>>y;
if(c==1){//change
for(int i=x;i<=y;){
if(a[i]>2){
update(i,(ll)d[a[i]]-a[i]);
a[i]=d[a[i]];
}
if(a[i]<=2) fa[i]=i+1;
if(i==findfa(i)) ++i;
else i=fa[i];
}
}else{//query
cout<<getsum(y)-getsum(x-1)<<'\n';
}
}
return ;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _=1;
// cin>>_;
while(_--){
solve();
}
return 0;
}