线段树,区间操作
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=100010;
__int64 sum[maxn<<2];
__int64 add[maxn<<2];
void PushUp(int rt)
{
if(sum[rt<<1]==sum[rt<<1|1])
sum[rt]=sum[rt<<1];
else
sum[rt]=-1;
}
void build(int l,int r,int rt)
{
add[rt]=0;
if(l==r)
{
scanf("%I64d",&sum[rt]);
add[rt]=0;
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
PushUp(rt);
}
void PushDown(int l,int r,int rt)
{
if(add[rt])
{
add[rt<<1]=add[rt<<1|1]=add[rt];
sum[rt<<1]=sum[rt<<1|1]=add[rt];
add[rt]=0;
}
}
void update1(int a,int b,__int64 x,int l,int r,int rt)
{
if(a<=l&&b>=r)
{
add[rt]=sum[rt]=x;
return ;
}
PushDown(l,r,rt);
int m=(l+r)>>1;
if(a<=m)
update1(a,b,x,l,m,rt<<1);
if(b>m)
update1(a,b,x,m+1,r,rt<<1|1);
PushUp(rt);
}
void update2(int a,int b,__int64 x,int l,int r,int rt)
{
if(sum[rt]!=-1&&(a<=l&&b>=r))
{
if(sum[rt]>x)
add[rt]=sum[rt]=__gcd(x,sum[rt]);
return ;
}
PushDown(l,r,rt);
int m=(l+r)>>1;
if(a<=m)
update2(a,b,x,l,m,rt<<1);
if(b>m)
update2(a,b,x,m+1,r,rt<<1|1);
PushUp(rt);
}
void query(int l,int r,int rt)
{
if(l==r)
{
printf("%I64d ",sum[rt]);
return ;
}
PushDown(l,r,rt);
int m=(l+r)>>1;
query(l,m,rt<<1);
query(m+1,r,rt<<1|1);
}
int main()
{
int T,n,m,a,b,x;
__int64 big;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
build(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d%I64d",&x,&a,&b,&big);
if(x==1)
update1(a,b,big,1,n,1);
else
{
update2(a,b,big,1,n,1);
}
}
query(1,n,1);
puts("");
}
return 0;
}