HDU-4027 开根号的线段树区间更新

来源:互联网 发布:淘宝网电动车配件 编辑:程序博客网 时间:2024/05/16 08:17

题意:
有100000个数,两种操作,0 i j表示将i, j这段的数字都开根号(向下取整),1 i j表示查询i, j之间的所有值的和(这题要用long long int)。
题解:
一开始没想出来开根号这玩意怎么做,后来看到别人说这玩意最大的值开个6,7次根号基本就完事了,就相通了,1开根号永远是1,如果要开根号,先判断区间是不是等于r-l+1(即每个都为1了),等于就直接return ,不等于就弄到最下层开根号,如此就可以得出答案了。

#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>using namespace std;#define lson root<<1,l,mid#define rson root<<1|1,mid+1,r #define LL long long int const int MAXN=100000+7;LL t[MAXN<<2],mark[MAXN<<2],a[MAXN];void build(int root,int l,int r){    if(l==r)    t[root]=a[l];    else    {        int mid=(l+r)/2;        build(lson);        build(rson);        t[root]=t[root<<1]+t[root<<1|1];    }}void update(int root,int l,int r,int L,int R){    if(r<L||l>R)    return ;    if(L<=l&&r<=R)    {        if(t[root]==r-l+1)        return ;    }    if(l==r)    {        t[root]=sqrt(t[root]);        return ;    }    int mid=(l+r)/2;    if(L<=mid)    update(lson,L,R);    if(R>mid)    update(rson,L,R);    t[root]=t[root<<1]+t[root<<1|1];}LL query(int root,int l,int r,int L,int R){    LL ans=0;    if(r<L||l>R)    return 0;    if(L<=l&&r<=R)    return t[root];    int mid=(l+r)/2;    if(L<=mid)    ans+=query(lson,L,R);    if(R>mid)    ans+=query(rson,L,R);    return ans;}int main(){    int n,m,i,k=1;    while(~scanf("%d",&n))    {        for(i=1;i<=n;i++)        scanf("%lld",&a[i]);        build(1,1,n);        scanf("%d",&m);        printf("Case #%d:\n",k++);        while(m--)        {            int x,y,z;            scanf("%d%d%d",&z,&x,&y);            if(x>y)            swap(x,y);            if(z==1)            printf("%lld\n",query(1,1,n,x,y));            else if(z==0)            update(1,1,n,x,y);        }        printf("\n");    }}
原创粉丝点击