题意:将一段中的值大于x的修改成gcd(x,num) 将一段的值都修改成x;
解法1:开两个标记和一个最小值的记录 然后往下的时候更新最小值比x大的区间
解法2:暴力,采用离线做法,用线段树记下每次点最后被set的数值,然后对于每个数进行暴力枚举gcd修改
标记法:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 111111
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
using namespace std;
#define ll int
#define inf (-(1<<31))
int set[maxn<<2],gc[maxn<<2],mi[maxn<<2];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void up(int rt){
mi[rt]=min(mi[ls],mi[rs]);
set[rt]=(set[ls]==set[rs]?set[ls]:inf);
}
void down(int rt){
if(set[rt]!=inf){
set[ls]=set[rs]=set[rt];
mi[ls]=mi[rs]=set[rt];
gc[ls]=gc[rs]=0;
set[rt]=inf;
}
if(gc[rt]){
gc[ls]=gcd(gc[ls],gc[rt]);
gc[rs]=gcd(gc[rs],gc[rt]);
mi[ls]=gcd(mi[ls],gc[rt]);
mi[rs]=gcd(mi[rs],gc[rt]);
gc[rt]=0;
}
}
void build(int rt,int l,int r){
set[rt]=inf;
gc[rt]=0;
if(l==r){
scanf("%d",&mi[rt]);
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
up(rt);
}
void _set(int rt,int l,int r,int L,int R,int w){
if(L<=l&&r<=R){
set[rt]=mi[rt]=w;
gc[rt]=0;
return;
}
down(rt);
if(L<=mid)_set(ls,l,mid,L,R,w);
if(mid<R)_set(rs,mid+1,r,L,R,w);
up(rt);
}
void _gcd(int rt,int l,int r,int L,int R,int w){
if(L<=l&&r<=R)
if(set[rt]!=inf||l==r){
if(mi[rt]>w){
if(set[rt]!=inf){
set[rt]=gcd(set[rt],w);
}
gc[rt]=gcd(gc[rt],w);
mi[rt]=gcd(mi[rt],w);
}
return;
}
down(rt);
if(L<=mid)_gcd(ls,l,mid,L,R,w);
if(mid<R)_gcd(rs,mid+1,r,L,R,w);
up(rt);
}
void query(int rt,int l,int r){
if(l==r){
printf("%d ",mi[rt]);return;
}
down(rt);
query(ls,l,mid);
query(rs,mid+1,r);
}
int main()
{
int _;
scanf("%d",&_);
while(_--) {
int n,m,op,l,r,w;
scanf("%d",&n);
build(1,1,n);
scanf("%d",&m);
while(m--){
scanf("%d%d%d%d",&op,&l,&r,&w);
if(op==1)_set(1,1,n,l,r,w);
else if(op==2)_gcd(1,1,n,l,r,w);
}
query(1,1,n);
printf("\n");
}
return 0;
}
暴力:
#include <cstdio>
#include <cstring>
#define maxn 100005
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
int n,q,a[maxn],x[maxn],p,l[maxn],r[maxn],op[maxn];
int s[maxn<<2];
int gcd(int a,int b){
return a?gcd(b%a,a):b;
}
void build(int rt,int l, int r){
s[rt]=-1;
if(l==r){
s[rt]=0;
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
}
void ins(int rt,int l,int r,int L,int R,int w){
if(L<=l&&r<=R){
s[rt]=w;
return;
}
if(s[rt]!=-1){
s[ls]=s[rt];
s[rs]=s[rt];
s[rt]=-1;
}
if(L<=mid)ins(ls,l,mid,L,R,w);
if(mid<R)ins(rs,mid+1,r,L,R,w);
}
int query(int rt,int l, int r, int k){
if(s[rt]!=-1)return s[rt];
if(k<=mid)return(query(ls,l,mid,k));
else return(query(rs,mid+1,r,k));
}
int main()
{
int _;
scanf("%d",&_);
while(_--){
scanf("%d",&n);
build(1,1,n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d%d%d",&op[i],&l[i],&r[i],&x[i]);
if(op[i]==1)ins(1,1,n,l[i],r[i],i);
}
for(int i=1;i<=n;i++){
p=query(1,1,n,i);
if(p)a[i]=x[p];
for(int j=p+1;j<=q;j++)
if(op[j]==2&&l[j]<=i&&r[j]>=i){
if(a[i]>x[j]){
a[i]=gcd(a[i],x[j]);
}
}
}
for(int i=1;i<=n;i++)printf("%d ",a[i]);
printf("\n");
}
return 0;
}