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;
}
posted on 2023-07-05 20:58  Qiansui  阅读(13)  评论(0编辑  收藏  举报