spoj 2713 Can you answer these queries IV

http://www.spoj.pl/problems/GSS4/

题意:给一个数列,有两个操作:

0 L,R,把区间[L,R]内的数开平方。

1 L,R,求区间[L,R]的和。

思路:因为一个1e18的数开方8次后必为1,所以时间复杂度为O(8*n+n*log(n))。

View Code
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#define LL long long
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const LL maxn = 100005;
LL as[maxn<<2],bs[maxn<<2];
LL cs[maxn],n,m,cas;
inline void pushUp(LL rt){
    as[rt] = as[lson] + as[rson];
    bs[rt] = max(bs[lson],bs[rson]);
}
void build(LL rt,LL l,LL r)
{
    LL md = (l + r) >> 1;
    if(l==r){
        as[rt]=cs[l];
        bs[rt]=cs[l];
        return;
    }
    build(lson,l,md);
    build(rson,md+1,r);
    pushUp(rt);
}
LL query(LL rt,LL l,LL r,LL L,LL R)
{
    LL md = (l + r) >> 1;
    if(L<=l && r<=R)return as[rt];
    if(R<=md)return query(lson,l,md,L,R);
    if(L>md)return  query(rson,md+1,r,L,R);
    return query(lson,l,md,L,md)+query(rson,md+1,r,md+1,R);
}
void update(LL rt,LL l,LL r,LL L,LL R)
{
    LL md = (l + r) >> 1;
    if(bs[rt]==1)return;
    if(l==r){
        as[rt]=bs[rt]=sqrt(as[rt]+0.0);
        return;
    }
    if(R<=md)update(lson,l,md,L,R);
    else if(L>md)update(rson,md+1,r,L,R);
    else update(lson,l,md,L,md),update(rson,md+1,r,md+1,R);
    pushUp(rt);
}
inline LL scan(){
    LL res=0,ch;
    while(!((ch=getchar())>='0' && ch<='9'))
    if(ch==EOF) return 1<<30;    res=ch-'0';
    while((ch=getchar())>='0' && ch<='9')
    res=res*10+(ch-'0');
    return res;
}
int main()
{
    while(scanf("%lld",&n)==1){
        for(LL i = 1; i <= n; ++ i)
        cs[i]=scan();
        build(1,1,n);
        scanf("%lld",&m);
        printf("Case #%lld:\n",++cas);
        while(m--){
            LL o,l,r;
            o=scan();l=scan();r=scan();
            if(l>r)l^=r^=l^=r;
            if(o)printf("%lld\n",query(1,1,n,l,r));
            else update(1,1,n,l,r);
        }
        puts("");
    }
    return 0;
}

posted on 2012-09-29 21:09  aigoruan  阅读(279)  评论(0)    收藏  举报

导航