• HDU 4027 Can you answer these queries?(线段树+优化)


    题目大意:

    一段区间,m此操作,0为区间里的数字开方,1为查询区间和。

     题解思路:

    线段树,开方操作无法传递,只能进行单点操作,但不优化的化会t;想了两种优化,都可以过。

    注意此题的l r大小不确定!

    第一种:对于ll以内的数,最多开6次方就会到达1,加一个标记数组,如果开放超过6次直接返回。

    第二种:如果区间和等于区间长度(区间内数字都为1)直接返回;。

    题目没有保证数据一定大于0,但是a了..就这样吧

    第一种优化:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #include<stack>
    
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    
    const ll maxn=2e5+10;
    
    using namespace std;
    
    ll n,m;
    
    ll tree[maxn*4],arr[maxn],cnt[4*maxn];//第一种约束
    
    void built(ll l,ll r,ll now)
    {
        ll mid=(l+r)/2;
        if(l==r)
        {
            tree[now]=arr[l];
            return ;
        }
        built(l,mid,now*2);
        built(mid+1,r,now*2+1);
        tree[now]=tree[now*2]+tree[now*2+1];
    }
    
    void updata(ll l,ll r,ll left,ll right,ll now)
    {
        if(cnt[now]>8) return ;
        ll mid=(l+r)/2;
        if(l==r&&left<=l&&l<=right)
        {
            tree[now]=sqrt(tree[now]);
            cnt[now]++;
            return ;
        }
        if(left<=mid) updata(l,mid,left,right,now*2);
        if(right>mid) updata(mid+1,r,left,right,now*2+1);
        tree[now]=tree[now*2]+tree[now*2+1];
        cnt[now]=min(cnt[now*2],cnt[now*2+1]);
    }
    
    ll query(ll l,ll r,ll left,ll right,ll now)
    {
        ll mid=(l+r)/2;
        if(left<=l&&r<=right)
        {
            return tree[now];
        }
        ll t=0;
        if(left<=mid) t+=query(l,mid,left,right,now*2);
        if(right>mid) t+=query(mid+1,r,left,right,now*2+1);
        return t;
    }
    
    int main(){
        ll mub=0;
    //    ll a=1000000000000000001;
    //    int k=0;
    //    while(a!=1)
    //    {
    //        cout<<a<<endl;
    //        a=sqrt(a);
    //        k++;
    //    }
    //    cout<<k<<endl;
        while(~scanf("%lld",&n))
        {
            mem(tree,0);
            mem(arr,0);
            mem(cnt,0);
            for(ll i=1;i<=n;i++)
            {
                scanf("%lld",arr+i);
            }
            built(1,n,1);
            scanf("%lld",&m);
            printf("Case #%lld:
    ",++mub);
            for(ll i=1;i<=m;i++)
            {
                ll l,r,cmd;
                scanf("%lld%lld%lld",&cmd,&l,&r);
                if(l>r) swap(l,r);
                if(cmd==0) updata(1,n,l,r,1);
                if(cmd==1)
                {
                    printf("%lld
    ",query(1,n,l,r,1));
                }
            }
            printf("
    ");
        }
        return 0;
    }

    第二种优化:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #include<stack>
    
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    
    const ll maxn=2e5+10;
    
    using namespace std;
    
    ll n,m;
    
    ll tree[maxn*4],arr[maxn];
    
    void built(ll l,ll r,ll now)
    {
        ll mid=(l+r)/2;
        if(l==r)
        {
            tree[now]=arr[l];
            return ;
        }
        built(l,mid,now*2);
        built(mid+1,r,now*2+1);
        tree[now]=tree[now*2]+tree[now*2+1];
    }
    
    void updata(ll l,ll r,ll left,ll right,ll now)
    {
        ll mid=(l+r)/2;
        if(tree[now]==(r-l+1)) return ;
        if(l==r&&left<=l&&l<=right)
        {
            tree[now]=sqrt(tree[now]);
            return ;
        }
        if(left<=mid) updata(l,mid,left,right,now*2);
        if(right>mid) updata(mid+1,r,left,right,now*2+1);
        tree[now]=tree[now*2]+tree[now*2+1];
    }
    
    ll query(ll l,ll r,ll left,ll right,ll now)
    {
        ll mid=(l+r)/2;
        if(left<=l&&r<=right)
        {
            return tree[now];
        }
        ll t=0;
        if(left<=mid) t+=query(l,mid,left,right,now*2);
        if(right>mid) t+=query(mid+1,r,left,right,now*2+1);
        return t;
    }
    
    int main(){
        ll mub=0;
    //    ll a=1000000000000000001;
    //    int k=0;
    //    while(a!=1)
    //    {
    //        cout<<a<<endl;
    //        a=sqrt(a);
    //        k++;
    //    }
    //    cout<<k<<endl;
        while(~scanf("%lld",&n))
        {
            mem(tree,0);
            mem(arr,0);
            for(ll i=1;i<=n;i++)
            {
                scanf("%lld",arr+i);
            }
            built(1,n,1);
            scanf("%lld",&m);
            printf("Case #%lld:
    ",++mub);
            for(ll i=1;i<=m;i++)
            {
                ll l,r,cmd;
                scanf("%lld%lld%lld",&cmd,&l,&r);
                if(l>r) swap(l,r);
                if(cmd==0) updata(1,n,l,r,1);
                if(cmd==1)
                {
                    printf("%lld
    ",query(1,n,l,r,1));
                }
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    Android众说纷纭分辨率
    Android初识Helloworld
    Android从零开始
    PHP使用APC获取上传文件进度
    央行mlf,SLF,PSL,MLF,SLO
    python的lxml解析器
    美国风投行业50年数据揭示的10条VC投资秘密法则
    osx的10款文本编辑器
    nano命令,vi ed pico sed joe emacs jed ex
    修改centos7/osx的MAC地址
  • 原文地址:https://www.cnblogs.com/minun/p/10473771.html
Copyright © 2020-2023  润新知