hdu 4027 Can you answer these queries?

题意:给你N个数,有M个操作,操作有两类,(1)"0 l r",表示将区间[l,r]里的每个数都开根号。(2)"1 l r",表示查询区间[l,r]里所有数的和。

虽然题目给出的数的范围达到了2^63次方,但是,最多开根号7次就会变成1。所以在每次更新的时候,判断,如果这个区间里的所有数被开根号的次数大于7,就不用再往下更新了,其次,因为每个数最多只会有7次开根号,所以在更新的时,可以一直更新到叶子结点。

#include 
#include 
#include 
#include 
using namespace std;

#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))
const int N=100005;
typedef long long LL;

struct node
{
    int lft,rht;
    LL cnt,sum;
    int mid(){return MID(lft,rht);}
    int len(){return rht-lft+1;}
};

int n,m;
LL y[N];

struct Segtree
{
    node tree[N*4];
    void up(int ind)
    {
        tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
        if(tree[LL(ind)].cnt>=7&&tree[RR(ind)].cnt>=7)
            tree[ind].cnt=7;
    }
    void build(int lft,int rht,int ind)
    {
        tree[ind].lft=lft;    tree[ind].rht=rht;
        tree[ind].cnt=0;    tree[ind].sum=0;
        if(lft==rht) tree[ind].sum=y[lft];
        else 
        {
            int mid=tree[ind].mid();
            build(lft,mid,LL(ind));
            build(mid+1,rht,RR(ind));
            tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
        }
    }
    void updata(int st,int ed,int ind)
    {
        if(tree[ind].cnt>=7) 
        {
            tree[ind].sum=tree[ind].len();
            return;
        }


        int lft=tree[ind].lft,rht=tree[ind].rht;
        if(st<=lft&&rht<=ed)
        {
            tree[ind].cnt+=1;
            if(lft==rht) 
                tree[ind].sum=(int)sqrt(tree[ind].sum*1.0);
            else
            {
                updata(st,ed,LL(ind));
                updata(st,ed,RR(ind));
                up(ind);
            }
        }
        
        else 
        {
            int mid=tree[ind].mid();
            if(st<=mid) updata(st,ed,LL(ind));
            if(ed> mid) updata(st,ed,RR(ind));
            up(ind);
        }
    }
    LL query(int st,int ed,int ind)
    {
        int lft=tree[ind].lft,rht=tree[ind].rht;
        if(st<=lft&&rht<=ed) return tree[ind].sum;
        else 
        {
            int mid=tree[ind].mid();
            LL sum1=0,sum2=0;
            if(st<=mid) sum1=query(st,ed,LL(ind));
            if(ed> mid) sum2=query(st,ed,RR(ind));
            return sum1+sum2;
        }    
    }
}seg;
int main()
{
    int t_cnt=0;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++) scanf("%I64d\n",&y[i]);
        scanf("%d",&m);


        seg.build(1,n,1);
        


        printf("Case #%d:\n",++t_cnt);
        for(int i=0;ic) swap(b,c);
            if(a==0) seg.updata(b,c,1);
            else printf("%I64d\n",seg.query(b,c,1));
        }
        puts("");
    }
    return 0;
}


你可能感兴趣的:(线段树及数据结构)