http://acm.hdu.edu.cn/showproblem.php?pid=4027

线段树成段更新的题目,开方次数有限,一个区间都是1就lazy。

仿hh风格的线段树,真漂亮啊

View Code
#include <iostream>
#include <cmath>
using namespace std ;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=100002 ;
typedef __int64 LL ;
LL sum[maxn<<2] ;
int lazy ;
void pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1] ;
}
void pushdown(int rt,int m)//区间上的点都到1,不进行更新 
{
    if(sum[rt]==m)
        lazy=1 ;
    else
        lazy=0 ;
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%I64d",&sum[rt]) ;
        return ;
    }
    int m=(l+r)>>1 ;
    build(lson) ;
    build(rson) ;
    pushup(rt) ;
}
void update(int L,int R,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=LL(sqrt((double)sum[rt])) ;
        return ;
    }
    pushdown(rt,r-l+1) ;
    if(lazy)
        return ;
    int m=(l+r)>>1 ;
    if(L<=m)
        update(L,R,lson) ;
    if(R>m)
        update(L,R,rson) ;
    pushup(rt) ;
}
LL query(int L,int R,int l,int r,int rt)
{
    if(L<=l && R>=r){
        return sum[rt] ;
    }
    int m=(l+r)>>1 ;
    LL ans=0 ;
    if(L<=m)    
        ans+=query(L,R,lson) ;
    if(R>m)
        ans+=query(L,R,rson) ;
    return ans ;
}
int main()
{
    int n ;
    int nCase=1 ;
    while(~scanf("%d",&n))
    {
        build(1,n,1) ;
        char op[2] ;
        int m ;
        scanf("%d",&m) ;
        printf("Case #%d:\n",nCase++) ;
        while(m--)
        {
            int a,b ;
            lazy=0 ;
            scanf("%s%d%d",op,&a,&b) ;
            if(a>b)a^=b^=a^=b ; 
            if(op[0]=='0')
                update(a,b,1,n,1) ;
            else
                printf("%I64d\n",query(a,b,1,n,1)) ;
        }
        putchar('\n') ;
    }
    return 0 ;
}