Ynoi 选做
[Ynoi Easy Round 2023] TEST_69
考虑类似花神游历各国的想法,一个值只会被有效操作 \(O(\log V)\) 次,考虑用线段树维护区间,问题在于快速判断一个区间 \([l,r]\) 是否全部无法进行有效操作,此时必然满足 \(a_i \mid x\),对于区间则是 \(\operatorname{lcm}\limits_{i=l}^{r} a_i \mid x\),当区间 \(\operatorname{lcm}\) 过大时显然不满足条件,我们只需要维护区间 \(\operatorname{lcm}\) 即可。
#include<iostream>
#include<cstdio>
using namespace std;
const long long INF=1145141919810114514;
long long my_gcd(long long num1,long long num2){
while(num2){
long long num3=num1%num2;
num1=num2;
num2=num3;
}
return num1;
}
long long my_lcm(long long num1,long long num2){
if(num1==-1 || num2==-1){
return -1;
}
else{
long long num3=my_gcd(num1,num2);
if(num1/num3>INF/num2){
return -1;
}
else{
return num1/num3*num2;
}
}
}
long long num[200010];
struct Node{
int l,r;
long long lcm;
unsigned int sum;
}a[800010];
void pushup(int id){
a[id].sum=a[id*2].sum+a[id*2+1].sum;
a[id].lcm=my_lcm(a[id*2].lcm,a[id*2+1].lcm);
}
void build(int id,int l,int r){
a[id].l=l;
a[id].r=r;
if(l==r){
a[id].lcm=num[l];
a[id].sum=a[id].lcm;
}
else{
int mid=(l+r)>>1;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
pushup(id);
}
}
void modify(int id,int l,int r,long long dif){
if(a[id].lcm!=-1 && dif%a[id].lcm==0){
return ;
}
if(a[id].l==a[id].r){
a[id].lcm=my_gcd(a[id].lcm,dif);
a[id].sum=a[id].lcm;
return ;
}
if(l<=a[id*2].r){
modify(id*2,l,r,dif);
}
if(a[id*2+1].l<=r){
modify(id*2+1,l,r,dif);
}
pushup(id);
}
unsigned int query(int id,int l,int r){
if(l<=a[id].l && a[id].r<=r){
return a[id].sum;
}
unsigned int ans=0;
if(l<=a[id*2].r){
ans+=query(id*2,l,r);
}
if(a[id*2+1].l<=r){
ans+=query(id*2+1,l,r);
}
return ans;
}
int main(){
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&num[i]);
}
build(1,1,n);
while(m--){
int cmd;
scanf("%d",&cmd);
if(cmd==1){
int l,r;
long long dif;
scanf("%d %d %lld",&l,&r,&dif);
modify(1,l,r,dif);
}
else{
int l,r;
scanf("%d %d",&l,&r);
printf("%u\n",query(1,l,r));
}
}
return 0;
}

浙公网安备 33010602011771号