P9989 分块题解 [Ynoi Easy Round 2023] TEST_69
一道 Ynoi 题怎能没有分块题解?
分块那么简单,为什么没人用?
前置芝士
- 分块
没了
题目解法
分块时,与别的题解不同,这里选择记录每块的覆盖标记的最大公约数来判断需不需要更新。
分成
所以总时间复杂度
发题解的时候复杂度写错了,总时间复杂度应该是
代码实现中使用了
AC code:
#include<bits/stdc++.h>
using namespace std;
int n,m,o,l,r,u,v,f=448;
long long a[200009],e,d[449],x;
unsigned s[449],ans;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0),cin>>n>>m;
for(int i=0;i<n;++i) cin>>a[i],s[i/f]+=a[i];
for(int i=0;i<m;++i){
cin>>o>>l>>r,--l,--r,u=l/f+1,v=r/f;
if(u>v){
if(o==1){cin>>x;if(d[v]!=1) for(int i=l;i<=r;++i) if(a[i]>1) e=__gcd(a[i],x),s[v]+=e-a[i],a[i]=e;}
else if(d[v]!=1){
ans=0;
for(int i=l;i<=r;++i) ans+=a[i];
cout<<ans<<"\n";
}
else cout<<r-l+1<<"\n";
}
else{
if(o==2){
ans=0;
if(d[u-1]!=1) for(int j=l,_=u*f;j<_;++j) ans+=a[j];
else ans+=u*f-l;
if(d[v]!=1) for(int j=v*f;j<=r;++j) ans+=a[j];
else ans+=r-v*f+1;
for(int j=u;j<v;++j) if(d[j]!=1) ans+=s[j];else ans+=f;
cout<<ans<<"\n";
}
else{
cin>>x;
if(d[u-1]!=1) for(int j=l,_=u*f;j<_;++j) if(a[j]>1) e=__gcd(a[j],x),s[u-1]+=e-a[j],a[j]=e;
if(d[v]!=1) for(int j=v*f;j<=r;++j) if(a[j]>1) e=__gcd(a[j],x),s[v]+=e-a[j],a[j]=e;
for(int j=u;j<v;++j) if(!d[j]||x%d[j]){
d[j]=__gcd(d[j],x);
if(d[j]!=1) for(int k=j*f,_=k+f;k<_;++k) if(a[k]>1) e=__gcd(a[k],x),s[j]+=e-a[k],a[k]=e;
}
}
}
}
return 0;
}