zoukankan      html  css  js  c++  java
  • LibreOJ 6281 数列分块入门5

    题目链接:https://loj.ac/problem/6281

    参考博客:https://blog.csdn.net/qq_36038511/article/details/79725027

    我一开始看到开方有点懵,看了上面的博客说2^31差不多5次开方就快变成1了,可以开标记数组,于是按照这个思路写了下,然后就过了,看来以后还要多看题意分析数据。

    代码:

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cstdio> 
    using namespace std;
    typedef long long LL;
    #define eps 1e-8
    #define INF 0x3f3f3f3f
    #define maxn 50010
    int n,m,k,t,block;
    int a[maxn],tag[maxn],sum[maxn],vis[maxn],lump[maxn];
    void kaif(int l,int r)//把l到r之间的数字开方 
    {
        for(int i=l;i<=min(lump[l]*block,r);i++)//直接改左边的不完整区间,同时该区间和 
        {
            sum[lump[l]]-=a[i];
            a[i]=sqrt(a[i]);
            sum[lump[l]]+=a[i];
        }
        if(lump[l]!=lump[r])
        {
            for(int i=(lump[r]-1)*block+1;i<=r;i++)
            {
                sum[lump[r]]-=a[i];
                a[i]=sqrt(a[i]);
                sum[lump[r]]+=a[i];
            }
        }
        for(int i=lump[l]+1;i<=lump[r]-1;i++)//记录这个区间开方了多少次 
        {
            tag[i]++;
        }
    }
    int cal(int x,int num)//求数字x开方num次得出的结果 
    {
        while(num--&&x>1)
        {
            x=sqrt(x);
        }
        return x;
    }
    int get_sum(int l,int r)//求区间和 
    {
        int ans=0;
        for(int i=l;i<=min(lump[l]*block,r);i++)//左区间暴力求和 
        {
            ans+=cal(a[i],tag[lump[l]]);
        }
        if(lump[l]!=lump[r])
        {
            for(int i=(lump[r]-1)*block+1;i<=r;i++)//右区间 
            {
                ans+=cal(a[i],tag[lump[r]]);
            }
        }
        for(int i=lump[l]+1;i<=lump[r]-1;i++) 
        {
            if(!vis[i])//如果vis[i]==0,表示区间i还有大于1的数字 
            {
                int flag=0;//标记看开方之后是否还有大于1的数字 
                sum[i]=0;//区间和清空 
                for(int j=(i-1)*block+1;j<=i*block;j++)
                {
                    a[j]=cal(a[j],tag[i]);
                    sum[i]+=a[j];//重新计算区间和 
                    if(a[j]>1)//只要有一个大于1 
                    flag=1;
                }
                tag[i]=0;//区间未开方数字清零 
                if(!flag)
                vis[i]=1;
            }
            ans+=sum[i];
        }
        return ans;
    }
    int main()
    {
        scanf("%d",&n);
        block=sqrt(n);
        fill(sum,sum+maxn-1,0);
        fill(tag,tag+maxn-1,0);
        fill(vis,vis+maxn-1,0);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            lump[i]=(i-1)/block+1;
            sum[lump[i]]+=a[i];
        }
        for(int i=1;i<=n;i++)
        {
            int op,l,r,w;
            scanf("%d%d%d%d",&op,&l,&r,&w);
            if(op==0)
            kaif(l,r);
            else
            printf("%d
    ",get_sum(l,r));
        }
        return 0;
    }
  • 相关阅读:
    BEC listen and translation exercise 44
    中译英12
    BEC listen and translation exercise 43
    中译英11
    BEC listen and translation exercise 42
    中译英10
    BEC listen and translation exercise 41
    中译英9
    BEC listen and translation exercise 40
    中译英8
  • 原文地址:https://www.cnblogs.com/6262369sss/p/9737197.html
Copyright © 2011-2022 走看看