看到这个题目好纠结来着,一时间不知道从何下手。
题目要求进行两种操作:1,将区间的值全部进行替换为x;2把区间内大于x的数变为gcd(num[i],x);
当然没看题目时限,以为会被卡时间..然后用成段更新去完成操作1,然后写到操作2的函数想到如果某个区间所有值都一样的话只需要进行一次操作就OK了。
题目要求是15秒...学长没用线段树暴力就过了,膜拜大神!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct node
{
int l,r,x,cover;//x基本没什么用处..可以用cover代替
}data[400050];
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
void build(int l,int r,int k)
{
data[k].l=l;
data[k].r=r;
data[k].cover=-1;
if(l==r)
{
scanf("%d",&data[k].x);
data[k].cover=data[k].x;
return ;
}
int mid=(l+r)/2;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
}
void updata(int l,int r,int x,int k)
{
if(data[k].l==l&&data[k].r==r)
{
data[k].cover=x;
return ;
}
if(data[k].l==data[k].r)//可以直接把这里的data[k].x替换为cover
{
data[k].x=x;
return ;
}
int mid=(data[k].l+data[k].r)/2;
if(data[k].cover!=-1)
{
updata(data[k].l,mid,data[k].cover,k*2);
updata(mid+1,data[k].r,data[k].cover,k*2+1);
data[k].cover=-1;
}
if(r<=mid)
updata(l,r,x,k*2);
else if(l>mid)
updata(l,r,x,k*2+1);
else
{
updata(l,mid,x,k*2);
updata(mid+1,r,x,k*2+1);
}
}
void change(int l,int r,int x,int k)
{
if(data[k].cover!=-1)
{
if(data[k].cover<x)
return ;
int gy=gcd(data[k].cover,x);
updata(l,r,gy,k);
return ;
}
int mid=(data[k].l+data[k].r)/2;
if(r<=mid)
change(l,r,x,k*2);
else if(l>mid)
change(l,r,x,k*2+1);
else
{
change(l,mid,x,k*2);
change(mid+1,r,x,k*2+1);
}
}
void print(int k)
{
if(data[k].cover!=-1)//如果某一段都一样直接就输出这段的值
{
for(int i=data[k].l;i<=data[k].r;i++)
printf("%d ",data[k].cover);
return ;
}
print(k*2);
print(k*2+1);
}
int main()
{
int n,q,t,i;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
build(1,n,1);
scanf("%d",&q);
while(q--)
{
int a,b,c,x;
scanf("%d %d %d %d",&x,&a,&b,&c);
if(x==1)
updata(a,b,c,1);
else
change(a,b,c,1);
}
print(1);
printf("\n");
}
return 0;
}