版权声明:蒟蒻Blog随意转载 https://blog.csdn.net/a1799342217/article/details/82858815
线段树
题目大意: 三个操作:区间取 ,区间覆盖,区间求和。
首先一个数取 经过log次就会变成 (奇数至少-1,偶数至少/2)。那么这个操作和区间开根号一样暴搞就好了。
注意暴搞的时候如果有区间覆盖的标记直接对标记取 。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 300005
#define M 10000005
#define F inline
using namespace std;
typedef long long LL;
struct tree{ int l,r,f1; LL f2,x; }t[N<<2];
int n,m,a[N],p[M],phi[M]; bool f[M];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
return l==r?EOF:*l++;
}
F int _read(){
int x=0,f=1; char ch=readc();
while (!isdigit(ch)){ if (ch=='-') f=-1; ch=readc(); }
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x*f;
}
F void Make(int n){
for (int i=2;i<=n;i++){
if (!f[i]) phi[p[++p[0]]=i]=i-1;
for (int j=1,v;j<=p[0]&&i*p[j]<=n;j++){
f[v=i*p[j]]=true;
if (i%p[j]==0){ phi[v]=phi[i]*p[j]; break; }
phi[v]=phi[i]*phi[p[j]];
}
}
}
F void pshp(int x){
t[x].f1=t[x<<1].f1&t[x<<1|1].f1;
t[x].x=t[x<<1].x+t[x<<1|1].x;
}
F void pshd(int x){
if (!t[x].f2) return; int l=x<<1,r=x<<1|1;
t[l].x=t[x].f2*(t[l].r-t[l].l+1);
t[r].x=t[x].f2*(t[r].r-t[r].l+1);
t[l].f2=t[r].f2=t[x].f2,t[l].f1=t[r].f1=t[x].f2=0;
}
void build(int x,int l,int r){
t[x]=(tree){l,r,0,0,0}; int mid=l+r>>1;
if (l==r) return void(t[x].x=a[l]);
build(x<<1,l,mid),build(x<<1|1,mid+1,r),pshp(x);
}
void nsrt(int x){
if (t[x].f2) return t[x].f2=phi[t[x].f2],t[x].x=t[x].f2*(t[x].r-t[x].l+1),void();
pshd(x); if (t[x].f1) return;
if (t[x].l==t[x].r) return void(t[x].f1=(t[x].x=phi[t[x].x])==1);
nsrt(x<<1),nsrt(x<<1|1),pshp(x);
}
void mdfy(int x,int l,int r){
if (t[x].l>r||t[x].r<l||t[x].f1) return;
if (t[x].l>=l&&t[x].r<=r) return nsrt(x);
pshd(x),mdfy(x<<1,l,r),mdfy(x<<1|1,l,r),pshp(x);
}
void mdfy(int x,int l,int r,LL w){
if (t[x].l>r||t[x].r<l) return;
if (t[x].l>=l&&t[x].r<=r)
return t[x].x=(t[x].f2=w)*(t[x].r-t[x].l+1),void(t[x].f1=w==1);
pshd(x),mdfy(x<<1,l,r,w),mdfy(x<<1|1,l,r,w),pshp(x);
}
LL srch(int x,int l,int r){
if (t[x].l>r||t[x].r<l) return 0;
if (t[x].l>=l&&t[x].r<=r) return t[x].x;
return pshd(x),srch(x<<1,l,r)+srch(x<<1|1,l,r);
}
int main(){
phi[1]=1,Make(1e7);
for (int T=_read();T;T--){
n=_read(),m=_read();
for (int i=1;i<=n;i++) a[i]=_read();
for (build(1,1,n);m;m--){
int f=_read(),l=_read(),r=_read();
if (f==1) mdfy(1,l,r);
if (f==2) mdfy(1,l,r,_read());
if (f==3) printf("%lld\n",srch(1,l,r));
}
}
return 0;
}