HDU-4027-Can you answer these queries?

这个题就是进行2种操作,

1、是对一个区间所有的数开平方,

2、求某个区间的和

思路:

用线段树进行更新区间,我们不难发现一个数经过一些次开方操作后总会变成1,而当一个数已经变成1以后我们便不用再对它进行开方操作,所以在更新区间的时候记录已经全部开方为1的区间,然后下次操作的时候则忽略,剩下的就是基本的线段树操作了,比较简单

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
const int maxn=1e5+100;
int n,m;
long long t[maxn*3],a[maxn];
void Build(int l,int r,int index)
{
    if(l==r)
    {
	t[index]=a[l];
	return;
    }
    int mid=(l+r)>>1;
    Build(l,mid,index<<1);
    Build(mid+1,r,index<<1|1);
    t[index]=t[index<<1]+t[index<<1|1];
}
void Update(int L,int R,int l,int r,int index)
{
    if(t[index]==R-L+1)
	return;
    if(L==R)
    {
	t[index]=sqrt((double)t[index]);
	return;
    }
    int mid=(L+R)>>1;
    if(r<=mid)
	Update(L,mid,l,r,index<<1);
    else if(l>mid)
	Update(mid+1,R,l,r,index<<1|1);
    else
    {
	Update(L,mid,l,mid,index<<1);
	Update(mid+1,R,mid+1,r,index<<1|1);
    }
    t[index]=t[index<<1]+t[index<<1|1];
}
long long Query(int L,int R,int l,int r,int index)
{
    if(l==L&&r==R)
	return t[index];
    int mid=(L+R)>>1;
    if(r<=mid)
	return Query(L,mid,l,r,index<<1);
    if(l>mid)
	return Query(mid+1,R,l,r,index<<1|1);
    return Query(L,mid,l,mid,index<<1)+Query(mid+1,R,mid+1,r,index<<1|1);
}
int main()
{
    int cas=1;
    while(scanf("%d",&n)!=EOF)
    {
	printf("Case #%d:\n",cas++);
	for(int i=1;i<=n;i++)
	    scanf("%I64d",&a[i]);
	Build(1,n,1);
	scanf("%d",&m);
	while(m--)
	{
	    int op,l,r;
	    scanf("%d%d%d",&op,&l,&r);
	    if(l>r)
		swap(l,r);
	    if(op==0)
		Update(1,n,l,r,1);
	    else
		printf("%I64d\n",Query(1,n,l,r,1));
	}
	printf("\n");
    }
    return 0;
}


你可能感兴趣的:(线段树)