• loj 6281 6284 数列分块入门 #5 #8


    题解:分块。操作只有开方,一个数经历几次开方后就会变成1。暴力开方,flag[ ] 标记此块是否全被开方为1。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int n,block,cnt,flag[maxn];
    long long sum[maxn],w[maxn];
    int get(int x);
    void update(int l,int r,int c);
    long long check(int l,int r);
    int main()
    {
      int i,op,l,r,c;
      scanf("%d",&n);
      
      block=sqrt(n);
      if(n%block) cnt=n/block+1;
      else cnt=n/block;
      
      for(i=1;i<=n;i++) 
      {
        scanf("%lld",&w[i]);
        sum[get(i)]+=w[i];
      }
      
      for(i=0;i<n;i++)
       {
         scanf("%d%d%d%d",&op,&l,&r,&c);
         if(op==0) update(l,r,c);
         else printf("%lld
    ",check(l,r));
       }
      system("pause");
      return 0;
    }
    int get(int x)
    {return (x-1)/block+1;}
    void update(int l,int r,int c)
    {
      int pre,end,k;
      pre=get(l);end=get(r);
      if(pre==end) 
       {
         for(k=l;k<=r;k++) 
         {
           sum[get(k)]-=w[k];
           w[k]=sqrt(w[k]);
           sum[get(k)]+=w[k];
         }
       }
      else
       {
         for(k=l;k<=min(pre*block,n);k++) 
         {
           sum[get(k)]-=w[k];
           w[k]=sqrt(w[k]);
           sum[get(k)]+=w[k];
         }
         for(k=(end-1)*block+1;k<=r;k++) 
         {
           sum[get(k)]-=w[k];
           w[k]=sqrt(w[k]);
           sum[get(k)]+=w[k];
         }
         for(k=pre+1;k<end;k++) 
         {
            if(flag[k]) continue;
            else
            {
              flag[k]=1;
              for(int j=(k-1)*block+1;j<=k*block;j++)
               {
                   sum[k]-=w[j];
                   w[j]=sqrt(w[j]);
                   sum[k]+=w[j];
                   if(w[j]!=1) flag[k]=0;
               }
            }
         }
       }
    }
    long long check(int l,int r)
    {
      long long ans=0;
      int pre,end,k,x;
      pre=get(l);end=get(r);
      if(pre==end) 
       { 
         for(k=l;k<=r;k++) 
           ans+=w[k];
       }
      else
       {
         for(k=l;k<=min(pre*block,n);k++) ans+=w[k];
         for(k=(end-1)*block+1;k<=r;k++) ans+=w[k];
         for(k=pre+1;k<end;k++) 
          {
            if(flag[k]) ans+=block;
            else ans+=sum[k];
          }
       }
      return ans;
    }

     

    题解:分块。与数列分块入门5类似。若某块全为同一个值,则用flag[ ]标记,直接计算,反之,暴力统计。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int n,block,w[maxn],flag[maxn];
    int get(int k)
    {return (k-1)/block+1;}
    void reset(int k);
    int check(int l,int r,int c);
    int main()
    {
      fill(flag,flag+maxn,-1);
      int i,l,r,c;
      scanf("%d",&n);
      block=sqrt(n);
      for(i=1;i<=n;i++) scanf("%d",&w[i]);
      for(i=0;i<n;i++)
      {
        scanf("%d%d%d",&l,&r,&c);
        printf("%d
    ",check(l,r,c));
      }
      system("pause");
      return 0;
    }
    void reset(int k)
    {
      if(flag[k]==-1) return ;
      for(int i=(k-1)*block+1;i<=min(k*block,n);i++)
        w[i]=flag[k];
      flag[k]=-1;
    }
    int check(int l,int r,int c)
    {
      int pre,end,k,ans=0;
      pre=get(l);end=get(r);
      reset(pre);
      if(pre==end)
       {
         for(k=l;k<=r;k++) 
         {
          if(w[k]==c) ans++;
          else w[k]=c;
         }
       }
       else
       {
         reset(end);
         for(k=l;k<=min(pre*block,n);k++) 
          {
            if(w[k]==c) ans++;
            else w[k]=c;
          }
         for(k=(end-1)*block+1;k<=r;k++) 
          {
            if(w[k]==c) ans++;
            else w[k]=c;
          }
         for(k=pre+1;k<end;k++) 
          {
            if(flag[k]!=-1)
             {
              if(flag[k]==c) ans+=block;
              else flag[k]=c;
             } 
            else
             {
               flag[k]=c;
               for(int i=(k-1)*block+1;i<=k*block;i++)
                {
                 if(w[i]==c) ans++;
                 else w[i]=c;
                }
             }
          }
       }
      return ans;
    }
    本博客仅为本人学习,总结,归纳,交流所用,若文章中存在错误或有不当之处,十分抱歉,劳烦指出,不胜感激!!!
  • 相关阅读:
    安卓开发环境搭建
    css3实现漂亮的按钮链接
    mouseover与mouseenter的区别
    踩了一个在body上添加多个代理事件的坑
    javascript与生活:papago行车记录仪播放器golife无卫星图修复方法
    grunt入门之windows下搭建一个最基本的grunt项目
    一个简单的跨浏览器的弹出窗口的实现
    如何查询mysql中执行效率低的sql语句
    用PHP读写音频文件的信息(支持WMA和MP3)
    PHP功能类[获取客户端IP、页面跳转]
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/11305725.html
Copyright © 2020-2023  润新知