人,只有自己站起来,这个世界才能属于他。|

园龄:粉丝:关注:

题解:P9989 [Ynoi Easy Round 2023] TEST_69

前言

注意到 test_69 没有 69 个 test。

思路分析

我们知道,每次对于一个数取 gcd 时,如果这个数改变,那么至少减小至原来的 12

然后考虑怎么判断区间每个数的 gcd 是否改变,不难发现维护区间 lcm,如果 k 是 区间 lcm 的倍数,那么区间里的数都不会改变。

问题又来了,维护初始序列的 lcm 可能炸 long long,又无法使用取模。

考虑只维护 lcm 是否 v,初始 lcm 均 v,如果递归过一次这个区间,那么 lcm 一定 v,所以这样做不会影响复杂度。

fan fact:像这样递归求 lcm 的复杂度为 O(nlogn)

代码实现

#include<bits/stdc++.h>
#define int __int128
using namespace std;
template<typename T> inline void read(T &a){
	a=0;
	char c=getchar();
	bool flag=false;
	while(!isdigit(c)){
		if(c=='-') flag=true;
		c=getchar();
	}
	while(isdigit(c)){
		a=(a<<1)+(a<<3)+(c^48);
		c=getchar(); 
	}
	a=(flag?-a:a);
}
template<typename T> inline void write(T a){
    if(a<0) putchar('-'),a=-a;
    if(a<10) putchar(a+'0');
    else write(a/10),putchar(a%10+'0');
}
const int mod=1ll<<32;
int n,m,a[200005],op,l,r,k;
int val_sum[400005],val_lcm[400005],ls[400005],rs[400005],dcnt,rt;
void pushup(int x){
	val_sum[x]=(val_sum[ls[x]]+val_sum[rs[x]])%mod;
	if(!val_lcm[ls[x]] || !val_lcm[rs[x]]) val_lcm[x]=0;
	else val_lcm[x]=val_lcm[ls[x]]/__gcd(val_lcm[ls[x]],val_lcm[rs[x]])*val_lcm[rs[x]];
}
void build(int l,int r,int &x){
	x=++dcnt;
	if(l==r){
		val_sum[x]=val_lcm[x]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls[x]);
	build(mid+1,r,rs[x]);
	pushup(x);
}
void modify(int l,int r,int ql,int qr,int k,int x){
	if(ql<=l && r<=qr){
		if(val_lcm[x] && k%val_lcm[x]==0) return;
		if(l==r){
			val_sum[x]=__gcd(val_sum[x],k);
			val_lcm[x]=__gcd(val_lcm[x],k);
			return;
		}
	}
	int mid=(l+r)>>1;
	if(ql<=mid) modify(l,mid,ql,qr,k,ls[x]);
	if(qr>=mid+1) modify(mid+1,r,ql,qr,k,rs[x]);
	pushup(x);
}
int query(int l,int r,int ql,int qr,int x){
	if(ql<=l && r<=qr) return val_sum[x];
	int mid=(l+r)>>1,ans=0;
	if(ql<=mid) ans=(ans+query(l,mid,ql,qr,ls[x]))%mod;
	if(qr>=mid+1) ans=(ans+query(mid+1,r,ql,qr,rs[x]))%mod;
	return ans;
}
signed main(){
	read(n),read(m);
	for(int i=1;i<=n;i++){
		read(a[i]);
	}
	build(1,n,rt);
	for(int i=1;i<=m;i++){
		read(op);
		if(op==1){
			read(l),read(r),read(k);
			modify(1,n,l,r,k,rt);
		}else{
			read(l),read(r);
			write(query(1,n,l,r,rt));
			puts("");
		}
	}
	return 0;
}

本文作者:Kenma

本文链接:https://www.cnblogs.com/Kenma/p/18706521

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _Kenma  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起