BZOJ3867 : Nice boat

时间:2021-01-08 15:29:05

每个点最多被修改$O(\log n)$次,线段树记录区间最值暴力更新。

#include<cstdio>
#define N 262145
int T,n,m,i,op,c,d,p,s[N],v[N],tag[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline void up(int x){v[x]=v[x<<1]>v[x<<1|1]?v[x<<1]:v[x<<1|1];tag[x]=tag[x<<1]==tag[x<<1|1]?tag[x<<1]:-1;}
inline void pb(int x){if(~tag[x])tag[x<<1]=tag[x<<1|1]=v[x<<1]=v[x<<1|1]=tag[x];}
void build(int x,int a,int b){
if(a==b){tag[x]=v[x]=s[a];return;}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
}
void change1(int x,int a,int b){
if(c<=a&&b<=d){tag[x]=v[x]=p;return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)change1(x<<1,a,mid);
if(d>mid)change1(x<<1|1,mid+1,b);
up(x);
}
void change2(int x,int a,int b){
if(v[x]<=p)return;
int mid=(a+b)>>1;
if(c<=a&&b<=d){
if(~tag[x])v[x]=tag[x]=gcd(tag[x],p);
else pb(x),change2(x<<1,a,mid),change2(x<<1|1,mid+1,b),up(x);
return;
}
pb(x);
if(c<=mid)change2(x<<1,a,mid);
if(d>mid)change2(x<<1|1,mid+1,b);
up(x);
}
void dfs(int x,int a,int b){
if(~tag[x]){for(;a<=b;a++)printf("%d ",tag[x]);return;}
int mid=(a+b)>>1;
dfs(x<<1,a,mid),dfs(x<<1|1,mid+1,b);
}
int main(){
read(T);
while(T--){
read(n);
for(i=1;i<=n;i++)read(s[i]);
build(1,1,n);
read(m);
while(m--)read(op),read(c),read(d),read(p),op==1?change1(1,1,n):change2(1,1,n);
dfs(1,1,n);
puts("");
}
return 0;
}