Can you answer these queries?-HDU4027 区间开方

题意:

给你n个数,两个操作,0为区间开方,1为区间求和

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

思路:

如果当该区间的数都为1,我们没必要进行开方操作,因为1开方还是1,否则找到每个叶子节点,进行开方操作

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int MAXN=1e5+5;
const int INF=0x7fffffff;
typedef long long ll;
ll lazy[MAXN<<2],tree[MAXN<<2];
void push_up(int node)
{
    tree[node]=tree[node<<1]+tree[node<<1|1];
}
void build(int node,int l,int r)
{
    if(l==r)
    {
        scanf("%lld",&tree[node]);
        return ;
    }
    int mid=(l+r)>>1;
    build(node<<1,l,mid);
    build(node<<1|1,mid+1,r);
    push_up(node);
}

void update(int node,int l,int r,int x,int y)
{
    //区间的长度等于区间内所有数之和则说明所有数都为1
    if(x<=l&&y>=r&&(r-l+1==tree[node]))
    {
        return;
    }
    if(l==r)
    {
        tree[node]=(ll)sqrt(tree[node]);return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)
        update(node<<1,l,mid,x,y);
    if(y>mid)
        update(node<<1|1,mid+1,r,x,y);
    push_up(node);
}
ll query(int node,int l,int r,int x,int y)
{
    if(x<=l&&y>=r)
    {
        return tree[node];
    }
    ll ans=0;
    int mid=(l+r)>>1;
    if(x<=mid)ans+=query(node<<1,l,mid,x,y);
    if(y>mid)ans+=query(node<<1|1,mid+1,r,x,y);
    return ans;
}
int main()
{
    int n;
    int case_=0;
    while(scanf("%d",&n)!=EOF)
    {
        printf("Case #%d:\n",++case_);
         build(1,1,n);
    int k;scanf("%d",&k);
    for(int i=1;i<=k;i++)
    {
        int op;scanf("%d",&op);
        int x,y;
        if(!op)
        {
            scanf("%d%d",&x,&y);update(1,1,n,min(x,y),max(x,y));
        }
        else
        {
            scanf("%d%d",&x,&y);
            printf("%lld\n",query(1,1,n,min(x,y),max(x,y)));
        }
        
    }printf("\n");
    }

    return 0;
}
posted @ 2020-01-21 20:19  grass_lin  阅读(109)  评论(0编辑  收藏  举报