操作1 的时候标记deng[rt]表示以下一段数都是与当前节点的值同样

下次操作2时直接对有deng标记的节点gcd更新

(可能还能够更简单)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 11111
#include <queue>
#include <vector>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid (r+l)>>1
const int maxn=100010;
int sum[maxn<<2] ,col[maxn<<2],deng[maxn<<2];
int gcd(int a,int b)
{
while(1)
{
if(b==0)
return a;
int t=b;
b=a%b;
a=t;
}
}
void pushup(int rt)
{
sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
}
void pushdown(int rt){
if(col[rt])
{
col[rt<<1]=col[rt<<1|1]=col[rt];
sum[rt<<1]=sum[rt<<1|1]=sum[rt];
col[rt]=0;
}
if(deng[rt])
{
deng[rt<<1]=deng[rt<<1|1]=deng[rt];
sum[rt<<1]=sum[rt<<1|1]=sum[rt];
deng[rt]=0;
}
}
void build(int l,int r,int rt)
{
col[rt]=deng[rt]=0;
if(r==l)
{
scanf("%d",&sum[rt]);
return;
}
int m=mid;
build(lson);
build(rson);
pushup(rt);
}
void out(int l,int r,int rt)
{
if(r==l)
{
printf("%d ",sum[rt]);
return;
}
pushdown(rt);
int m=mid;
out(lson);
out(rson);
}
void update1(int L,int R,int num,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
col[rt]=1;
deng[rt]=1;
sum[rt]=num;
return ;
}
pushdown(rt);
int m=mid;
if(L<=m) update1(L,R,num,lson);
if(m<R) update1(L,R,num,rson);
pushup(rt);
}
void update2(int L,int R,int num,int l,int r,int rt)
{
if(sum[rt]<num)
return ;
if(deng[rt]&&L<=l&&r<=R)
{
sum[rt]=gcd(sum[rt],num);
col[rt]=1;
deng[rt]=0;
return ;
}
if(l==r)
{
sum[rt]=gcd(sum[rt],num);
return ;
}
pushdown(rt);
int m=mid;
if(L<=m) update2(L,R,num,lson);
if(m<R) update2(L,R,num,rson);
pushup(rt);
}
int main()
{
int t,n,q;
// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
build(1,n,1);
scanf("%d",&q);
int op,l,r,x;
for(int i=0;i<q;i++)
{
scanf("%d%d%d%d",&op,&l,&r,&x);
if(op==1)
update1(l,r,x,1,n,1);
else
update2(l,r,x,1,n,1);
}
out(1,n,1);
printf("\n");
}
return 0;
}

05-11 09:24