/*
一个10^5的序列,有10^5个操作,每个操作为a,b,c
a=0时将b到c区间内的数都开根号下取整,a=1时求b到c段的和
其中所有数的和不超过2^63。
可以发现所有的数最多开7次方,就会变成1了,再开方就不变了。
所以定一个标记allone表示这一段已经全是1了,以后的开房遇到allone为true就不向下进行了,提高效率。
线段树求和的变型,线段树提高效率的关键在于寻找合适的lazy标记,到满足一定条件的时候就不继续更新到点。

*注意在HDOJ里,64位整数,定义用__int64或longlong,输入输出只能用%I64d
*/
//4675978 2011-09-29 08:46:46 Accepted 4027 734MS 6368K 2308 B G++ nkhelloworld
//4675979 2011-09-29 08:46:53 Accepted 4027 437MS 6424K 2308 B C++ nkhelloworld
#include <cstdio>
#include <cmath>
#define MAXN 100010
struct SEGMENTTREE
{
    int lt,rt;
    long long sum;
    bool allone;
}tree[MAXN*4+1];
int n,m;
void swap(int &a,int &b)
{
    int t = a;  a = b;  b = t;
}
void buildsegtree(int root,int lt,int rt)
{
    tree[root].lt = lt; tree[root].rt = rt;
    if(lt == rt)
    {
        scanf("%I64d",&tree[root].sum);
        if(tree[root].sum == 1) tree[root].allone = true;
        else    tree[root].allone = false;
        return ;
    }
    int mid = (lt + rt)>>1;
    buildsegtree(root<<1, lt, mid);
    buildsegtree(root<<1|1, mid+1, rt);
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
    tree[root].allone = tree[root<<1].allone & tree[root<<1|1].allone;
}

void update(int root,int lt,int rt)
{
    if(tree[root].allone)
        return ;
    if(tree[root].lt == tree[root].rt)
    {
        tree[root].sum = (long long)(sqrt((double)tree[root].sum));
        if(tree[root].sum == 1)
            tree[root].allone = true;
        return ;
    }
    int mid = (tree[root].lt + tree[root].rt)>>1;
    if(rt <= mid)
        update(root<<1,lt,rt);
    else if(lt > mid)
        update(root<<1|1,lt,rt);
    else
    {
        update(root<<1,lt,mid);
        update(root<<1|1,mid+1,rt);
    }
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
    tree[root].allone = tree[root<<1].allone & tree[root<<1|1].allone;
}

long long query(int root,int lt,int rt)
{
    if(tree[root].lt == lt && tree[root].rt == rt)
        return tree[root].sum;
    int mid = (tree[root].lt + tree[root].rt)>>1;
    if(rt <= mid)
        return query(root<<1,lt,rt);
    else if(lt > mid)
        return query(root<<1|1,lt,rt);
    else
    {
        return query(root<<1,lt,mid) + query(root<<1|1,mid+1,rt);
    }
}

int main()
{
    int a,b,c,numcase = 0;
    while(scanf("%d",&n)!=EOF)
    {
        printf("Case #%d:\n",++numcase);
        buildsegtree(1,1,n);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(b>c) swap(b,c);
            if(a == 0)
                update(1,b,c);
            else
                printf("%I64d\n",query(1,b,c));
        }
        printf("\n");
    }
    return 0;
}

posted on 2011-09-29 11:18  NKHe!!oWor!d  阅读(174)  评论(0编辑  收藏  举报