传送门
题意:
给你n个数,Q次操作,操作分两类
第一类操作(type1):将区间内
[l,r]
[
l
,
r
]
的数改成
x
x
第二类操作(type2):将区间内
a[i]>x
a
[
i
]
>
x
的改成
gcd(a[i],x)
g
c
d
(
a
[
i
]
,
x
)
你需要输出Q次操作后的序列
今天考试的第二题,还是比较良心的,结果考场上打多了一个else挂掉了(暴哭)
由于操作是区间全部修改,所以肯定有一段一段的是相同的。
考虑维护一个标记num:对于当前管理的一段区间数值是否全部相同,相同num=这个数值,不同num=-1,然后注意下放标记和上传标记即可。
还可以维护一个区间最大值mx,如果mx < x的话说明没有可以更新的,那么可以提速。
注意原题多组数据。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
struct trnode
{
int l,r,lc,rc;
int num;//区间内的数是否相同。
}tr[510000]; int trlen;
int a[510000];
void bt(int l,int r)
{
trlen++;
int now=trlen;
tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;
if(l==r) tr[now].num=a[l];
if(l<r)
{
int mid=(l+r)/2;
tr[now].lc=trlen+1;bt(l,mid);
tr[now].rc=trlen+1;bt(mid+1,r);
tr[now].num=(tr[tr[now].lc].num==tr[tr[now].rc].num)?tr[tr[now].lc].num:-1;
}
}
void change1(int now,int L,int R,int x)
{
if(L<=tr[now].l && tr[now].r<=R)
{
tr[now].num=x;
return;
}
else
{
int l=tr[now].l,r=tr[now].r,lc=tr[now].lc,rc=tr[now].rc;
int mid=(l+r)/2;
if(tr[now].num>-1) tr[lc].num=tr[now].num,tr[rc].num=tr[now].num;
if(R<=mid) change1(lc,L,R,x);
else if(mid+1<=L) change1(rc,L,R,x);
else
{
change1(lc,L,mid,x);
change1(rc,mid+1,R,x);
}
tr[now].num=(tr[lc].num==tr[rc].num)?tr[lc].num:-1;
}
}
void change2(int now,int L,int R,int x)
{
if(L<=tr[now].l && tr[now].r<=R)
{
if(tr[now].num>-1)
{
if(tr[now].num>x)
tr[now].num=gcd(tr[now].num,x);
return;
}
}
int l=tr[now].l,r=tr[now].r,lc=tr[now].lc,rc=tr[now].rc;
int mid=(l+r)/2;
if(tr[now].num>-1) tr[lc].num=tr[now].num,tr[rc].num=tr[now].num;
if(R<=mid) change2(lc,L,R,x);
else if(mid+1<=L) change2(rc,L,R,x);
else
{
change2(lc,L,mid,x);
change2(rc,mid+1,R,x);
}
tr[now].num=(tr[lc].num==tr[rc].num)?tr[lc].num:-1;
}
void print(int now,int l,int r)
{
if(tr[now].num!=-1)
{
for(int i=tr[now].l;i<=tr[now].r;i++) printf("%d ",tr[now].num);
}
else
{
int lc=tr[now].lc,rc=tr[now].rc;
if(tr[now].num>-1) tr[lc].num=tr[now].num,tr[rc].num=tr[now].num;
int mid=(l+r)/2;
print(tr[now].lc,l,mid);
print(tr[now].rc,mid+1,r);
}
}
int main()
{
// freopen("b.in","r",stdin);
// freopen("b.out","w",stdout);
int T;scanf("%d",&T);
while(T--)
{
int n,Q;scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
trlen=0; bt(1,n);
scanf("%d",&Q);
while(Q--)
{
int flag,l,r; int x;
scanf("%d%d%d%d",&flag,&l,&r,&x);
if(flag==1) change1(1,l,r,x);
else change2(1,l,r,x);
}
print(1,1,n);
printf("\n");
}
return 0;
}