HDU 4027 <线段树,区间√>

题目连接

题意

给出一个区间,每次把[l,r]内的值√,维护区间和。

坑:

£:l会比r大,swap.
£: 当f[i].sum=f[i].r-f[i].l+1;,不修改。因为保证每个数都大于等于1,当每个数都为1的时候,此区间不需要开根。
//纯手工
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long  LL;
const int maxn=100000+10;
LL a[maxn];
struct node
{
    int l,r;
    LL sum;
};
node f[maxn*4];
void maketree(int i,int l,int r)
{
    f[i].r=r;
    f[i].l=l;
    f[i].sum=0;
    if(l==r)
    {
        f[i].sum=a[l];
        return ;
    }
    int mid =(r+l)>>1;
    maketree(i<<1,l,mid);
    maketree(i<<1|1,mid+1,r);
    f[i].sum=f[i<<1].sum+f[i<<1|1].sum;
}
void update(int i,int l,int r)
{
    if(f[i].sum==(f[i].r-f[i].l+1))//全部为一的时候,不需要开根号
        return ;
    if(f[i].l==f[i].r)
    {
        f[i].sum=sqrt(f[i].sum*1.0);
        return ;
    }
    int mid =(f[i].l+f[i].r)>>1;
    if(r<=mid)
        update(i<<1,l,r);
    else if(l>=mid+1)
        update(i<<1|1,l,r);
    else
    {
        update(i<<1,l,mid);
        update(i<<1|1,mid+1,r);
    }
    f[i].sum=f[i<<1].sum+f[i<<1|1].sum;//递归
}
LL sum(int i,int l,int r)
{
    if(f[i].l==l&&f[i].r==r)
        return f[i].sum;
    LL ret=0;
    int mid =(f[i].l+f[i].r)>>1;
    if(r<=mid)
        ret=sum(i<<1,l,r);
    else if(l>=mid+1)
        ret=sum(i<<1|1, l, r);
    else
        ret=sum(i<<1, l, mid)+sum(i<<1|1,mid+1,r);
    return ret;
}
int main ()
{
    int n,m,k=0;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        maketree(1, 1, n);
        scanf("%d",&m);
        printf("Case #%d:
",++k);
        int T,l,r;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&T,&l,&r);
            if(l>r)
                swap(l,r);
            if(T==0)
                update(1, l, r);
            else
                printf("%lld
",sum(1, l, r));
        }
        printf("
");
    }
    return 0;
}
想的太多,做的太少。
原文地址:https://www.cnblogs.com/pealicx/p/6115620.html