HDU5634 Rikka with Phi

版权声明:蒟蒻Blog随意转载 https://blog.csdn.net/a1799342217/article/details/82858815

线段树

题目传送门

题目大意: 三个操作:区间取 φ \varphi ,区间覆盖,区间求和。

首先一个数取 φ \varphi 经过log次就会变成 1 1 (奇数至少-1,偶数至少/2)。那么这个操作和区间开根号一样暴搞就好了。

注意暴搞的时候如果有区间覆盖的标记直接对标记取 φ \varphi

代码:

#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;
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/82858815
phi