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

    #6281. 数列分块入门 5

    题目:传送门 

    简要题意:

       给出一个长为 n 的数列,以及 n 个操作,操作涉及区间开方,区间求和。


    题解:

       怎么说...这道题loj的数据有点水。

       和bzoj花神游历各国是一样的...但是loj没有卡掉不完全优化的代码。

       基础操作就不说了(同分块4),主要讲优化吧:

       不难发现,因为开方后我们是向下取整的,那么如果一直开方下去,整个序列一定会变成0或1。那么如果当前区间都是0或1就没有操作的必要了嘛。

       讲到这里思路就已经很清晰了,但是一开始的时候本蒟蒻并没有优化头尾的块,依然在loj AC了...bzoj就挂了,事实证明:暴力加优化才是分块真正的难点!


    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long LL;
     8 LL n,m,a[110000],sum[110000];
     9 LL block,pos[110000];
    10 bool v[110000];
    11 void reset(LL x)
    12 {
    13     if(v[x])return ;
    14     v[x]=1;sum[x]=0;
    15     for(int i=(x-1)*block+1;i<=x*block;i++)
    16     {
    17         a[i]=sqrt(a[i]);sum[x]+=a[i];
    18         if(a[i]>1)v[x]=0;
    19     }
    20 }
    21 void update(LL l,LL r)
    22 {
    23     if(!v[pos[l]])
    24     {
    25         for(int i=l;i<=min(pos[l]*block,r);i++)
    26         {
    27             sum[pos[l]]-=a[i];
    28             a[i]=sqrt(a[i]);
    29             sum[pos[l]]+=a[i];
    30         }
    31         v[pos[l]]=1;for(int i=(pos[l]-1)*block+1;i<=pos[l]*block;i++)if(a[i]>1)v[pos[l]]=0;
    32     }
    33     if(pos[l]!=pos[r])
    34     {
    35         if(!v[pos[r]])
    36         {
    37             for(int i=(pos[r]-1)*block+1;i<=r;i++)
    38             {
    39                 sum[pos[r]]-=a[i];
    40                 a[i]=sqrt(a[i]);
    41                 sum[pos[r]]+=a[i];
    42             }
    43             v[pos[r]]=1;for(int i=(pos[r]-1)*block;i<=pos[r]*block;i++)if(a[i]>1)v[pos[r]]=0;
    44         }
    45     }
    46     for(int i=pos[l]+1;i<=pos[r]-1;i++)reset(i);
    47 }
    48 void sol(LL l,LL r)
    49 {
    50     LL ans=0;
    51     for(int i=l;i<=min(pos[l]*block,r);i++)ans+=a[i];
    52     if(pos[l]!=pos[r])
    53         for(int i=(pos[r]-1)*block+1;i<=r;i++)
    54             ans+=a[i];
    55     for(int i=pos[l]+1;i<=pos[r]-1;i++)ans+=sum[i];
    56     printf("%lld
    ",ans);
    57 }
    58 int main()
    59 {
    60     memset(v,false,sizeof(v));
    61     scanf("%lld",&n);
    62     for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    63     block=sqrt(n);
    64     for(int i=1;i<=n;i++)
    65     {
    66         pos[i]=(i-1)/block+1;
    67         sum[pos[i]]+=a[i];
    68     }
    69     for(int i=1;i<=n;i++)
    70     {
    71         LL opt,l,r,c;scanf("%lld%lld%lld%lld",&opt,&l,&r,&c);
    72         if(opt==0)update(l,r);
    73         else sol(l,r);
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    a标签跳转新页面
    js或jquery实现页面打印(局部打印)
    js实现点击定位最顶端
    js实现pdf对页面的打印
    js动态创建input
    sha1加密算法
    JsonHelper修改4.0
    List<T>做数据源绑定的问题
    VS2013智能提示
    Newtonsoft.Json(Json.Net)学习笔记
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8580640.html
Copyright © 2011-2022 走看看