zoukankan      html  css  js  c++  java
  • loj 6728 6729 数列分块入门 #2 #3

    题解:分块。用vector维护每个块,二分查找。及时更新边块即可。当前值+此块增加的值<c*c,即当前值<c*c-块同时增加的值。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int w[maxn],n,block,cnt,sum[maxn];
    vector<int> v[50005];
    int get(int x);
    void update(int l,int r,int c);
    int check(int l,int r,int c);
    void reset(int k);
    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("%d",&w[i]);
         v[get(i)].push_back(w[i]);
       }
      for(i=1;i<=cnt;i++) sort(v[i].begin(),v[i].end());
      for(i=0;i<n;i++)
       {
         scanf("%d%d%d%d",&op,&l,&r,&c);
         if(op==0) update(l,r,c);
         else printf("%d
    ",check(l,r,c*c));
       }
      system("pause");
      return 0;
    }
    int get(int x)
    {return (x-1)/block+1;}
    void reset(int k)
    {
      v[k].clear();
      for(int i=(k-1)*block+1;i<=min(k*block,n);i++) v[k].push_back(w[i]);
      sort(v[k].begin(),v[k].end());
    }
    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++) w[k]+=c;
         reset(pre);
       }
      else
       {
         for(k=l;k<=min(pre*block,n);k++) w[k]+=c;
         for(k=(end-1)*block+1;k<=r;k++) w[k]+=c;
         for(k=pre+1;k<end;k++) sum[k]+=c;
         reset(pre);reset(end);
       }
    }
    int check(int l,int r,int c)
    {
      int ans=0,pre,end,k,x;
      pre=get(l);end=get(r);
      if(pre==end) 
       { 
         for(k=l;k<=r;k++) 
           if(w[k]+sum[pre]<c) ans++;
       }
      else
       {
         for(k=l;k<=min(pre*block,n);k++) if(w[k]+sum[get(k)]<c) ans++;
         for(k=(end-1)*block+1;k<=r;k++) if(w[k]+sum[get(k)]<c) ans++;
         for(k=pre+1;k<end;k++) 
          {
            x=c-sum[k];
            ans+=lower_bound(v[k].begin(),v[k].end(),x)-v[k].begin();
          }
       }
      return ans;
    }

    题解:分块。与数列分块入门 2类似,稍微修改即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int w[maxn],n,block,cnt,sum[maxn];
    vector<int> v[50005];
    int get(int x);
    void update(int l,int r,int c);
    int check(int l,int r,int c);
    void reset(int k);
    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("%d",&w[i]);
         v[get(i)].push_back(w[i]);
       }
      for(i=1;i<=cnt;i++) sort(v[i].begin(),v[i].end());
      for(i=0;i<n;i++)
       {
         scanf("%d%d%d%d",&op,&l,&r,&c);
         if(op==0) update(l,r,c);
         else printf("%d
    ",check(l,r,c));
       }
      system("pause");
      return 0;
    }
    int get(int x)
    {return (x-1)/block+1;}
    void reset(int k)
    {
      v[k].clear();
      for(int i=(k-1)*block+1;i<=min(k*block,n);i++) v[k].push_back(w[i]);
      sort(v[k].begin(),v[k].end());
    }
    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++) w[k]+=c;
         reset(pre);
       }
      else
       {
         for(k=l;k<=min(pre*block,n);k++) w[k]+=c;
         for(k=(end-1)*block+1;k<=r;k++) w[k]+=c;
         for(k=pre+1;k<end;k++) sum[k]+=c;
         reset(pre);reset(end);
       }
    }
    int check(int l,int r,int c)
    {
      int ans=-0x3f3f3f3f,pre,end,k,x,flag=0;
      pre=get(l);end=get(r);
      if(pre==end) 
       { 
        for(k=l;k<=r;k++) 
         {
           if(w[k]+sum[pre]<c) 
            {
              flag=1;
              ans=max(ans,w[k]+sum[pre]);
            }
         }
       }
      else
       {
         for(k=l;k<=min(pre*block,n);k++) 
          if(w[k]+sum[get(k)]<c)
             flag=1,ans=max(ans,w[k]+sum[get(k)]);
             
         for(k=(end-1)*block+1;k<=r;k++) 
           if(w[k]+sum[get(k)]<c) 
             flag=1,ans=max(ans,w[k]+sum[get(k)]);
             
         for(k=pre+1;k<end;k++) 
          {
            x=c-sum[k];
            int index=lower_bound(v[k].begin(),v[k].end(),x)-v[k].begin();
            if(index>0&&v[k][index-1]+sum[k]<c)
             flag=1,ans=max(ans,v[k][index-1]+sum[k]);
          }
       }
      return flag==1?ans:-1;
    }
    本博客仅为本人学习,总结,归纳,交流所用,若文章中存在错误或有不当之处,十分抱歉,劳烦指出,不胜感激!!!
  • 相关阅读:
    大三上学期周总结
    《代码整洁之道》阅读笔记(三)
    大三上学期周总结
    【测试技能】常用adb命令记录
    【Jmeter】Mac本JMeter实现压力测试实例
    【音视频】IP 地区定位,有坑
    【服务器】mp(edge)内存使用情况扩展
    【python】TypeError: 'Response' object is not subscriptable
    【python】单元测试框架改造接口自动化case
    【git】放弃本地修改,拉取远端最新代码
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/11305617.html
Copyright © 2011-2022 走看看