hdu5634[线段树]
我走过你来时的路.
http://acm.hdu.edu.cn/showproblem.php?pid=5634
加深了对于线段树多标记的理解.
//33985526 2020-09-21 20:27:56 Accepted 5634 3010MS 77568K 2730 B G++ mainland
#include <bits/stdc++.h>
using namespace std;
#define inc(i,a,b) for(int i=a;i<=b;i++)
#define dec(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mst(a,b) memset(a,b,sizeof a)
#define pb push_back
inline int read(){
char ch=getchar();int f=1,x=0;
while(!isdigit(ch)) { if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){ x=x*10+ch-'0';ch=getchar();}
return f*x;
}
const int maxv=1e7+10;
// 因为prime的个数很明显达不到maxv的级别
// 这里如果不放心,可以打表来计算一下这里prime开多大比较合适
int prime[maxv/10];
bool np[maxv];
int phi[maxv];
int tot;
// phi 是积性函数,所以可以利用筛来计算
void sieve(int n){
tot=0; np[1]=true; phi[1]=1;
inc(i,2,n){
if(np[i]==false){ prime[++tot]=i; phi[i]=i-1; }
inc(j,1,tot){
if(prime[j]*i>n) break;
np[i*prime[j]]=true;
if(i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
const int N=3e5+10;
#define o rt
#define ls o<<1
#define rs o<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
struct Tree{
// 表示该节点覆盖的是区间[l,r]
int l,r;
// sum表示区间的和
// same==0 表示该区间内的数并不是相同的,
// 如果same!=0,表示区间内的数是相同的,且值为same
ll sum,same;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
#define same(x) tree[x].same
}tree[N<<2];
inline void pushup(int o){
sum(o)=sum(ls)+sum(rs);
if(same(ls)==same(rs)) same(o)=same(ls);
else same(o)=0;
}
inline void pushdown(int o){
if(same(o)){
int l=l(o);
int r=r(o);
int m=(l+r)>>1;
same(ls)=same(rs)=same(o);
sum(ls)=1LL*same(o)*(m-l+1);
sum(rs)=1LL*same(o)*(r-m);
same(o)=0;
}
}
inline void build(int l,int r,int o){
l(o)=l;
r(o)=r;
if(l==r) {
scanf("%lld",&sum(o));
same(o)=sum(o);
return ;
}
int m=(l+r)>>1;
build(lson);build(rson);
pushup(o);
}
inline void update1(int ql,int qr,int o){
int l=l(o),r=r(o);
if(ql<=l && r<=qr && same(o)){
same(o)=phi[same(o)];
sum(o)=1LL*same(o)*(r-l+1);
return ;
}
pushdown(o);
int m=(l+r)>>1;
if(ql<=m) update1(ql,qr,ls);
if(m<qr) update1(ql,qr,rs);
pushup(o);
return ;
}
inline void update2(int ql,int qr,int x,int o){
int l=l(o),r=r(o);
if(ql<=l&& r<=qr){
same(o)=x;
sum(o)=1LL*(r-l+1)*x;
return;
}
pushdown(o);
int m=(l+r)>>1;
if(ql<=m) update2(ql,qr,x,ls);
if(m<qr) update2(ql,qr,x,rs);
pushup(o);
}
ll query(int ql,int qr,int o){
int l=l(o),r=r(o);
if(ql<=l && r<=qr) return sum(o);
pushdown(o);
int m=(l+r)>>1;
ll ret=0;
if(ql<=m) ret+=query(ql,qr,ls);
if(m<qr) ret+=query(ql,qr,rs);
return ret;
}
int main(){
sieve(10000000);
bool show=true; show=false;
int T;scanf("%d",&T);while(T--){
int n,m;scanf("%d%d",&n,&m);
build(1,n,1);
inc(i,1,m){
int op;scanf("%d",&op);
if(op==1){
int l,r;scanf("%d%d",&l,&r);
update1(l,r,1);
}else if(op==2){
int l,r,x;scanf("%d%d%d",&l,&r,&x);
update2(l,r,x,1);
}else {
int l,r;scanf("%d%d",&l,&r);
printf("%lld\n",query(l,r,1));
}
}
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!