分块算法

题解:

分块好写好调好对拍。。

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

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

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

教主的魔法 

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

分块+块内二分查找

注意二分查找的时候如果可能比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;
}
原文地址:https://www.cnblogs.com/yinwuxiao/p/9507021.html