多校第4场,又是一道线段树。
题意:有两种操作:一种是把一段区间内的值变为x,另一种是把一段区间内比x大的值变为x与他的最大公约数。
线段树节点记录一段区间内的最大值。
开始只用了一个延时标记函数,标记这一段区间是否需要变为x。结果超时了,后来加了一个标记函数,表示某段区间最后一次进行操作1的时间。如果,一段区间在进行了操作1后,他前面的所有操作都是无效的。
具体代码如下:之前代码存在错误,数据水了。现代码更正如下:
<pre name="code" class="cpp"><pre name="code" class="cpp">#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL __int64
#define maxn 400000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
LL col[maxn],sum[maxn],flag[maxn];
struct node
{
int t,l,r;
LL x;
}nod[100009];
LL gcd(LL a,LL b)
{
if(b==0)return a;
gcd(b,a%b);
}
void pushupSum(int rt)
{
sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
}
void pushdownCol(int rt,int m)
{
if(col[rt] != -1)
{
col[rt<<1] = col[rt<<1|1] = col[rt];
sum[rt<<1] = col[rt];
sum[rt<<1|1] = col[rt];
col[rt] = -1;
}
}
void pushupFlag(int rt)
{
flag[rt] = min (flag[rt<<1],flag[rt<<1|1]);
}
void build(int l,int r,int rt)
{
col[rt] = -1;
flag[rt]= -1;
if(l==r)
{
scanf("%I64d",&sum[rt]);
return ;
}
int m = (l+r)>>1;
build(lson);
build(rson);
pushupSum(rt);
}
void update1(int l,int r,int rt,int L,int R,LL x,int num)
{
if(flag[rt]>num)return ;
if(l>=L&&r<=R)
{
col[rt] = x;
sum[rt] = x;
return ;
}
pushdownCol(rt,r-l+1);
int m = (l+r)>>1;
if(m>=L)update1(lson,L,R,x,num);
if(m<R) update1(rson,L,R,x,num);
pushupSum(rt);
}
void update2(int l,int r,int rt,int L, int R,LL x,int num)
{
if(flag[rt]>num)return ;
if(sum[rt]<=x)return ;
if(l==r)
{
sum[rt] = gcd(sum[rt],x);
return ;
}
pushdownCol(rt,r-l+1);
int m = (l+r)>>1;
if(m>=L) update2(lson,L,R,x,num);
if(m<R) update2(rson,L,R,x,num);
pushupSum(rt);
}
void update3(int l,int r,int rt,int L,int R,int num)
{
if(l>=L&&r<=R)
{
flag[rt] = num;
return ;
}
int m =(l+r)>>1;
if(m>=L)update3(lson,L,R,num);
if(m<R) update3(rson,L,R,num);
pushupFlag(rt);
}
void query(int l,int r,int rt)
{
if(l==r)
{
printf("%I64d ",sum[rt]);
return ;
}
pushdownCol(rt,r-l+1);
int m = (l+r)>>1;
query(lson);
query(rson);
}
int main()
{
int T,n,m,i,j,k;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
build(1,n,1);
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d%d%d%I64d",&nod[i].t,&nod[i].l,&nod[i].r,&nod[i].x);
if(nod[i].t==1)update3(1,n,1,nod[i].l,nod[i].r,i);
}
for(i=0;i<m;i++)
{
if(nod[i].t==1)update1(1,n,1,nod[i].l,nod[i].r,nod[i].x,i);
else update2(1,n,1,nod[i].l,nod[i].r,nod[i].x,i);
}
query(1,n,1);
printf("\n");
}
return 0;
}