zoukankan      html  css  js  c++  java
  • 分块算法

    题解:

    分块好写好调好对拍。。

    大部分的题目可以用其他数据结构来解决

    但是对于一部分题目分块有自己的优势

    下面这两道题目是只能用分块算法来做

    教主的魔法 

    线段树套平衡树是可以维护这个东西的,但是这题预处理复杂度

    分块+块内二分查找

    注意二分查找的时候如果可能比h要小

    这是个老问题了。。。

    // luogu-judger-enable-o2
    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    #define mid ((h+t)/2)
    #define me(x) memset(x,0,sizeof(x))
    const int N=1e6+10;
    int n,q,block;
    int a[N],b[N],pos[N],lazy[N];
    IL bool cmp(int x,int y)
    {
      return(x<y);
    }
    IL void reset(int x)
    {
      int h=(x-1)*block+1,t=min(x*block,n);
      rep(i,h,t) b[i]=a[i];
      sort(b+h,b+t+1,cmp);
    }
    IL int find(int x,int v)
    {
      int h=(x-1)*block+1,t=min(x*block,n);
      int tmp=t;
      while (h<t)
      {
        if (b[mid]<v) h=mid+1;
        else t=mid;
      }
      if (tmp==t&&b[t]<v) t++;
      return(tmp-t+1);
    }
    IL void updata(int x,int y,int v)
    {
      if (pos[x]==pos[y])
      {
        rep(i,x,y) a[i]+=v;
      } else
      {
        int l1=pos[x]*block;
        rep(i,x,l1) a[i]+=v;
        rep(i,(pos[y]-1)*block+1,y) a[i]+=v;
      }
      reset(pos[x]); reset(pos[y]);
      rep(i,pos[x]+1,pos[y]-1) lazy[i]+=v;
    }
    IL int query(int x,int y,int v)
    {
      int sum=0;
      if (pos[x]==pos[y])
      {
        rep(i,x,y) if (a[i]+lazy[pos[i]]>=v) sum++;
      }
      else
      {
        int l1=pos[x]*block;
        rep(i,x,l1) if (a[i]+lazy[pos[i]]>=v) sum++;
        rep(i,(pos[y]-1)*block+1,y) if (a[i]+lazy[pos[i]]>=v) sum++;
      }
      rep(i,pos[x]+1,pos[y]-1) 
      {
        sum+=find(i,v-lazy[i]);
      }
      return sum;
    }
    int main()
    {
      ios::sync_with_stdio(false);
      cin>>n>>q;
      block=sqrt(n);
      rep(i,1,n) cin>>a[i],pos[i]=(i-1)/block+1;
      int m=(n-1)/block+1;
      rep(i,1,m) reset(i); 
      rep(i,1,q)
      {
        char ch[5]; int x,y,v;
        cin>>ch>>x>>y>>v;
        if(ch[0]=='M') updata(x,y,v);
        else cout<<query(x,y,v)<<endl;
      }
      return 0;
    }

    6285. 数列分块入门 9

    这道题尽显分块优势

    首先有一个结论是a&b=a&b众数

    这个很显然

    然后就可以搞分块了

    另外分块的时候要求查询x-y中为c的个数

    这个也是可以分块的

    这里非常巧妙做到O(1)查询

    具体的可以看clj的论文

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    const int N=1e5+100;
    const int N2=320;
    const int INF=1e9;
    int pos[N],pos2[N],b[N],c[N],d[N];
    int f[N2][N],ph[N2],pt[N2],p[N2][N2];
    int cnt[N2][N2][N2],now[N2][N];
    int n,m,block;
    struct re{
      int a,b;
    }a[N];
    bool cmp(re x,re y)
    {
      return(x.a<y.a);
    }
    void reset1(int x)
    {
      int h=(x-1)*block+1,t=min(x*block,n);
      int cnt1=0;
      rep(i,h,t) c[i]=b[i];
      sort(c+h,c+t+1);
      rep(i,h,t)
      { 
        if (c[i]!=c[i-1]||(i==h)) ++cnt1;
        f[x][c[i]]=cnt1;
      }
      rep(i,1,t-h+1)
      { 
        rep(j,1,t-h+1)
          cnt[x][i][j]=cnt[x][i-1][j]; 
        cnt[x][i][f[x][b[i+h-1]]]++;
      }
      rep(i,h,t) now[x][b[i]]++;
    }
    IL int query2(int o,int x)
    {
      return now[pos[o]-1][x]+cnt[pos[o]][o-ph[pos[o]]+1][f[pos[o]][x]];
    }
    #define query(h,t,x) query2(t,x)-query2(h-1,x)
    void reset(int x)
    {
      int h=(x-1)*block+1,t=min(x*block,n);
      ph[x]=h; pt[x]=t;
      int ans1=0,ans2=INF;
      rep(i,h,t)
      {
        int aa=query(h,t,b[i]);
        if (aa>ans1||(ans1==aa&&b[i]<ans2)) ans1=aa,ans2=b[i];
      }
      p[x][x]=ans2;
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      ios::sync_with_stdio(false);
      cin>>n;
      rep(i,1,n) cin>>a[i].a,a[i].b=i;
      sort(a+1,a+n+1,cmp);
      a[0].a=INF;
      int cnt=0;
      rep(i,1,n)
        if(a[i].a!=a[i-1].a) b[a[i].b]=++cnt,pos2[cnt]=a[i].a;
        else b[a[i].b]=cnt;
      block=sqrt(n);
      rep(i,1,n) pos[i]=(i-1)/block+1;
      m=(n-1)/block+1;
      rep(i,1,m) reset1(i);
      rep(i,1,m)
        rep(j,1,n)
          now[i][j]+=now[i-1][j];
      rep(i,1,m) reset(i);
      rep(i,1,m-1)
        rep(j,1,m-i)
        {
          int ans1=query(ph[j],pt[j+i],p[j][j+i-1]),ans2=p[j][j+i-1];
          int h=ph[j+i],t=pt[j+i];
          rep(k,h,t)
          {
            int kk=query(ph[j],pt[j+i],b[k]);
            if (kk>ans1||(ans1==kk&&b[k]<ans2)) ans1=kk,ans2=b[k];
          }
          p[j][i+j]=ans2;
        }
      rep(i,1,n)
      {
        int x,y;
        cin>>x>>y;
        int ans1=0,ans2=INF;
        if (pos[x]==pos[y])
        {
          rep(i,x,y)
          {
            int kk=query(x,y,b[i]);
            if (kk>ans1||(kk==ans1&&b[i]<ans2)) ans1=kk,ans2=b[i];
          }
        } else
        {
          if (pos[x]+1<=pos[y]-1) ans2=p[pos[x]+1][pos[y]-1],ans1=query(x,y,ans2);
          else ans2=INF,ans1=0;
          int l1=pos[x]*block;
          rep(i,x,l1)
          {
            int kk=query(x,y,b[i]);
            if(kk>ans1||(kk==ans1&&b[i]<ans2)) ans1=kk,ans2=b[i]; 
          }
          rep(i,(pos[y]-1)*block+1,y)
          {
            int kk=query(x,y,b[i]);
            if(kk>ans1||(kk==ans1&&b[i]<ans2)) ans1=kk,ans2=b[i];
          }
        }
        cout<<pos2[ans2]<<endl;
      }
      return 0;
    }
  • 相关阅读:
    OCP-1Z0-052-V8.02-28题
    OCP-1Z0-052-V8.02-27题
    OCP-1Z0-052-V8.02-26题
    OCP-1Z0-052-V8.02-25题
    Oracle DB 管理还原数据
    Flex中常见的图
    OCP-1Z0-052-V8.02-23题
    OCP-1Z0-052-V8.02-21题
    OCP-1Z0-052-V8.02-20题
    OCP-1Z0-052-V8.02-19题
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9507021.html
Copyright © 2011-2022 走看看