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;
}

 

 

posted @ 2012-11-29 18:15  紫忆  阅读(340)  评论(0编辑  收藏  举报