首页 > 代码库 > HDU 4027 Can you answer these queries?(线段树,区间更新,区间查询)

HDU 4027 Can you answer these queries?(线段树,区间更新,区间查询)

题目

 

线段树

简单题意:

区间(单点?)更新,区间求和

 更新是区间内的数开根号并向下取整

这道题不用延迟操作

 

 

//注意:
//1:查询时的区间端点可能前面的比后面的大;
//2:优化:因为每次更新都是开平方,同一个数更新有限次数就一直是1了,所以可以这样优化
#include <stdio.h>  
#include<math.h>
#define N 100010  
  
#define LL __int64
#define lson l,m,rt<<1  
#define rson m+1,r,rt<<1|1  

LL sum[N<<2];  
  
void PushUP(int rt)  
{  
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];  
}  

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]=(__int64)sqrt((double)sum[rt]);
        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 ret=0;  
    if(L<=m)   ret+=Query(L,R,lson);  
    if(R>m)    ret+=Query(L,R,rson);  
    return ret;  
}  
  
int main()  
{  
    int m,n,id=1; 
    LL anss;
    while(scanf("%d",&n)!=EOF)
    {
        Build(1,n,1);
        scanf("%d",&m);  
        printf("Case #%d:\n",id++);
        while(m--)  
        {  
            int q,a,b,c;  
            scanf("%d%d%d",&q,&a,&b); 
            if(a>b)
            {
                c=a;
                a=b;
                b=c;
            }

            anss=Query(a,b,1,n,1);
            if(q==1)  
            {  
                printf("%I64d\n",anss);  
            }  
            else  
            {  
                if(anss != b-a+1)
                    Update(a,b,1,n,1);  
            }  
        }
        printf("\n");
    }
    return 0;  
}  
View Code

 

虽然我自己不会写线段树,但是以后遇到 区间(单点?)更新,区间求和,这可以当底板修改一下就可以用了,毕竟这里的用法还是蛮好理解的