hdu4027

http://acm.hdu.edu.cn/showproblem.php?pid=4027

思路:这一题不能用成段更新,那样会超时的。仔细看题,会发现一个2的64次方被开8次就会变成1,也就是如果一段区间和等于它的右极限-左极限+1的话,就代表这段区间不用再被开方了......接下来就是区间求和的问题了..............

#include<iostream>

#include<math.h>

using namespace std;

struct node

{

	__int64 l,r,num;

}str[900010];

__int64 yy[500006],ans=0;

void build(__int64 i,__int64 l,__int64 r)

{

	__int64 mid=(l+r)/2;

	str[i].l=l;

	str[i].r=r;

	str[i].num=0;

	if(l==r)

	{

		str[i].num=yy[l];

		return;

	}

	build(i*2,l,mid);

	build(i*2+1,mid+1,r);

	str[i].num=str[i*2].num+str[i*2+1].num;

}

void updata(__int64 i,__int64 l,__int64 r)

{

	__int64 mid=(str[i].l+str[i].r)/2;

	if(l==str[i].l&&r==str[i].r)

	{

		if(str[i].num==r-l+1)

			return;

		else

			if(l==r)

			{

				str[i].num=sqrt((double)str[i].num);

				__int64 count=i/2;

				while(count>=1)

				{

					str[count].num=str[count*2].num+str[count*2+1].num;

					count/=2;

				}

				return ;

			}

	}

	if(r<=mid)

		updata(i*2,l,r);

	else

		if(l>mid)

			updata(i*2+1,l,r);

		else

		{

			updata(i*2,l,mid);

			updata(i*2+1,mid+1,r);

		}

}

__int64 getsum(__int64 i,__int64 l,__int64 r)

{

	__int64 mid=(str[i].l+str[i].r)/2;

	if(str[i].l==l&&str[i].r==r)

	{

		return str[i].num;

	}

	else

		if(r<=mid)

			return getsum(i*2,l,r);

			else

			     if(l>mid)

					 return getsum(i*2+1,l,r);

				 else

					 return getsum(i*2,l,mid)+getsum(i*2+1,mid+1,r);

}

int main()

{

	__int64 n,temp=0;

	while(scanf("%I64d",&n)>0)

	{

		__int64 i;

		for(i=1;i<=n;i++)

		{

			scanf("%I64d",&yy[i]);

		}

		__int64 m;

		scanf("%I64d",&m);

		build(1,1,n);

		printf("Case #%I64d:\n",++temp);

		for(i=1;i<=m;i++)

		{

			__int64 a,b,c;

			scanf("%I64d%I64d%I64d",&a,&b,&c);

			if(b>c)

			{

				__int64 asd;

				asd=b;

				b=c;

				c=asd;

			}

			if(a==0)

			{

				updata(1,b,c);

			}

			else 

				if(a==1)

				{

					ans=0;

					ans=getsum(1,b,c);

					printf("%I64d\n",ans);

				}

		}

		printf("\n");

	}

	return 0;

}

 

 

你可能感兴趣的:(HDU)