HDU 4902 2014多校联赛第四场1006 Nice boat

看到这个题目好纠结来着,一时间不知道从何下手。

题目要求进行两种操作: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;
}

你可能感兴趣的:(线段树,lazy操作)