CF920F SUM and REPLACE

题面传送门
一眼就是势能线段树的模板题。
关于欧拉函数的上界我不会证,这里证一个复杂度下界。
对于每一个数 x x x,其最大的约数最大是 n 2 \frac{n}{2} 2n,故对于每一个 n 2 < y < x \frac{n}{2}<y<x 2n<y<x都必定不是 x x x的约数,所以复杂度下界 l o g n logn logn,总复杂度 n l o g n nlogn nlogn
代码实现:

#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,k,x,y,sx,a[300039],pr[1000039],fs[1000039],flag[1000039],sum[1200039],ph,s[1000039],ans,tot,pus,now,last;
long long f[1200039];
inline void jianshu(int l,int r,int now){
	if(l==r){
		f[now]=a[l];
		if(a[l]==1||a[l]==2)sum[now]=1;
		return ;
	}
	int m=(l+r)>>1;
	jianshu(l,m,now<<1);
	jianshu(m+1,r,now<<1|1);
	sum[now]=sum[now<<1]&sum[now<<1|1];
	f[now]=f[now<<1]+f[now<<1|1];
}
inline void get(int l,int r,int now){
	if(l==r){
		f[now]=s[f[now]];
		if(f[now]==1||f[now]==2)sum[now]=1;
		return ;
	}
	int m=(l+r)>>1;
	if(x<=m&&!sum[now<<1]) get(l,m,now<<1);
	if(y>m&&!sum[now<<1|1]) get(m+1,r,now<<1|1);
	sum[now]=sum[now<<1]&sum[now<<1|1]; 
	f[now]=f[now<<1]+f[now<<1|1];
}
inline long long find(int l,int r,int now){
	if(x<=l&&r<=y) return f[now];
	int m=(l+r)>>1;
	long long fs=0;
	if(x<=m) fs+=find(l,m,now<<1);
	if(y>m) fs+=find(m+1,r,now<<1|1);
	return fs;
}
int main(){
	register int i,j;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++) scanf("%d",&a[i]),ans=max(ans,a[i]);
	for(i=2;i<=ans;i++){
		if(!fs[i]) pr[++ph]=i,flag[i]=i;
		for(j=1;j<=ph&&pr[j]*i<=1e6;j++){
			fs[pr[j]*i]=1;
			flag[pr[j]*i]=pr[j];
			if(i%pr[j]==0) break;
		}
	}
	for(i=1;i<=ans;i++){
		now=i;tot=0;last=0;s[i]=1;
		while(now!=1){
			if(last!=flag[now]) s[i]*=tot+1,last=flag[now],tot=0;
			tot++;now/=flag[now];
		}
		s[i]*=tot+1;
		//printf("%d ",flag[i]);
	}
	//printf("\n");
	jianshu(1,n,1);
	for(i=1;i<=m;i++){
		scanf("%d",&sx);
		if(sx==1){
			scanf("%d%d",&x,&y);
			get(1,n,1);
		}
		else{
			scanf("%d%d",&x,&y);
			printf("%lld\n",find(1,n,1));
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值