HDU 4027 Can you answer these queries?(线段树)

题意:

给一个数组序列, 数组长度为100000 

两种操作: 一种操作是将某一个固定区间所有数开方(向下取整)

另一种操作是询问某个区间的所有数字之和。

思路:

数据范围2^64,最多开6、7次就到1,所以判断当sum[rt]==r-l+1时 return(相当于剪枝),由于更新比较特别,此题不需要lazy数组。最后注意query的数据左不一定小于右,所以要交换一下,还有就是以后不要混用scanf和cin了。。。WA了无数次就是因为这个!!!

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=100005;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qpow(ll a,ll b){ll t=1;while(b){if(b%2){t=(t*a)%mod;b--;}a=(a*a)%mod;b/=2;}return t;}
ll inv(ll a,ll p){return qpow(a,p-2);}
ll a[maxn<<2],sum[maxn<<2];
void pushUp(ll rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(ll l,ll r,ll rt)
{
    sum[rt]=0;
    if(l==r)
    {
        sum[rt]=a[l];
        return ;
    }
    ll m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushUp(rt);
}
void update(ll L,ll R,ll l,ll r,ll rt)
{
    if(L <= l && r <= R &&sum[rt]==r-l+1)
    {
        return ;
    }
    if(l==r)
    {
        sum[rt]=(ll)sqrt((double)sum[rt]);
        return ;
    }
    ll m=(l+r)>>1;
    if(L<=m)    update(L,R,l,m,rt<<1);
    if(R>m)     update(L,R,m+1,r,rt<<1|1);
    pushUp(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt)
{
    if(L<=l&&r<=R)
    {
        return sum[rt];
    }
    ll m=(l+r)>>1;
    ll ans=0;
    if(L<=m)    ans+=query(L,R,l,m,rt<<1);
    if(R>m)     ans+=query(L,R,m+1,r,rt<<1|1);
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    int n,cas=0;
    while(~scanf("%d",&n))
    {
       // memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        build(1,n,1);
        ll m;

        scanf("%lld",&m);
        printf("Case #%d:\n",++cas);
        while(m--)
        {
           ll t,b,c;
           scanf("%lld%lld%lld",&t,&b,&c);
           if(b>c) swap(b,c);
           if(!t)
           {
               update(b,c,1,n,1);
           }
           else
           {
               printf("%lld\n",query(b,c,1,n,1));
           }
        }
        puts("");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值