您的位置:首页 > 其它

分块

2018-02-06 21:31 134 查看

1.区间加, 查询单点值

struct block
{
static const int __=50005;
static const int _b_=300;
ll a[__];int n,bsz,bel[__];
ll ad[_b_];

ll operator[](int x){return a[x]+ad[bel[x]];}

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/bsz+1;
}

void add(int l,int r,ll val)
{
for(int i=l;i<=min(r,bel[l]*bsz);i++)
a[i]+=val;
if(bel[l]==bel[r])return;
for(int i=bel[l]+1;i<bel[r];i++)
ad[i]+=val;
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
a[i]+=val;
}

void clear(){memset(ad,0,sizeof(ad));}
}b;


2.区间加, 查询区间内小于某个数的个数

struct block
{
static const int __=50005;
static const int _b_=300;
ll a[__];int n,bsz,bel[__];
ll ad[_b_];
vector<ll>ord[_b_];

ll operator[](int x){return a[x]+ad[bel[x]];}

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
ord[bel[i]=(i-1)/bsz+1].pb(a[i]);
for(int i=1;i<=bel
;i++)
sort(ord[i].begin(),ord[i].end());
}

void rebuild(int x)
{
int r=(bel
==x)?n:(x*bsz);
ord[x].clear();
for(int i=(x-1)*bsz+1;i<=r;i++)
ord[x].pb(a[i]);
sort(ord[x].begin(),ord[x].end());
}

void add(int l,int r,ll val)
{
for(int i=l;i<=min(r,bel[l]*bsz);i++)
a[i]+=val;
rebuild(bel[l]);
if(bel[l]==bel[r])return;
for(int i=bel[l]+1;i<bel[r];i++)
ad[i]+=val;
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
a[i]+=val;
rebuild(bel[r]);
}

int get_min(int l,int r,ll val)
{
int res=0;
for(int i=l;i<=min(r,bel[l]*bsz);i++)
if(a[i]+ad[bel[i]]<val)res++;
if(bel[l]==bel[r])return res;
for(int i=bel[l]+1;i<bel[r];i++)
res+=lower_bound(ord[i].begin(),ord[i].end(),val-ad[i])-ord[i].begin();
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
if(a[i]+ad[bel[i]]<val)res++;
return res;
}

void clear(){memset(ad,0,sizeof(ad));}
}b;


3.区间加, 查询区间内小于某个数的最大的元素

struct block
{
static const int __=100005;
static const int _b_=400;
ll a[__];int n,bsz,bel[__];
ll ad[_b_];
vector<ll>ord[_b_];

ll operator[](int x){return a[x]+ad[bel[x]];}

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
ord[bel[i]=(i-1)/bsz+1].pb(a[i]);
for(int i=1;i<=bel
;i++)
sort(ord[i].begin(),ord[i].end());
}

void rebuild(int x)
{
int r=(bel
==x)?n:(x*bsz);
ord[x].clear();
for(int i=(x-1)*bsz+1;i<=r;i++)
ord[x].pb(a[i]);
sort(ord[x].begin(),ord[x].end());
}

void add(int l,int r,ll val)
{
for(int i=l;i<=min(r,bel[l]*bsz);i++)
a[i]+=val;
rebuild(bel[l]);
if(bel[l]==bel[r])return;
for(int i=bel[l]+1;i<bel[r];i++)
ad[i]+=val;
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
a[i]+=val;
rebuild(bel[r]);
}

int get_pre(int l,int r,ll val)
{
ll res=-1;
for(int i=l;i<=min(r,bel[l]*bsz);i++)
if(a[i]+ad[bel[i]]<val)
res=max(res,a[i]+ad[bel[i]]);
if(bel[l]==bel[r])return res;
for(int i=bel[l]+1;i<bel[r];i++)
{
int x=lower_bound(ord[i].begin(),ord[i].end(),val-ad[i])-ord[i].begin();
if(x)res=max(res,ord[i][x-1]+ad[i]);
}
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
if(a[i]+ad[bel[i]]<val)
res=max(res,a[i]+ad[bel[i]]);
return res;
}

void clear(){memset(ad,0,sizeof(ad));}
}b;


4.区间加, 查询区间和

struct block
{
static const int __=100005;
static const int _b_=400;
ll a[__];int n,bsz,bel[__];
ll ad[_b_],sum[_b_];

ll operator[](int x){return a[x]+ad[bel[x]];}

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
sum[bel[i]=(i-1)/bsz+1]+=a[i];
}

void add(int l,int r,ll val)
{
for(int i=l;i<=min(r,bel[l]*bsz);i++)
a[i]+=val,sum[bel[i]]+=val;
if(bel[l]==bel[r])return;
for(int i=bel[l]+1;i<bel[r];i++)
ad[i]+=val;
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
a[i]+=val,sum[bel[i]]+=val;
}

ll get_sum(int l,int r,ll mod)
{
ll res=0;
for(int i=l;i<=min(r,bel[l]*bsz);i++)
res=(res+a[i]+ad[bel[i]])%mod;
if(bel[l]==bel[r])return res;
for(int i=bel[l]+1;i<bel[r];i++)
res=(res+sum[i]+ad[i]*bsz)%mod;
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
res=(res+a[i]+ad[bel[i]])%mod;
return res;
}

void clear(){memset(ad,0,sizeof(ad));}
}b;


5.区间开方, 查询区间和

struct block
{
static const int __=100005;
static const int _b_=400;
ll a[__];int n,bsz,bel[__];
ll sum[_b_];bool all_one[_b_];

ll operator[](int x){return a[x];}

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
sum[bel[i]=(i-1)/bsz+1]+=a[i];
}

void sqt(int l,int r)
{
for(int i=l;i<=min(r,bel[l]*bsz);i++)
{
int x=(int)sqrt(a[i]);
sum[bel[i]]+=x-a[i],a[i]=x;
}
if(bel[l]==bel[r])return;
for(int i=bel[l]+1;i<bel[r];i++)
{
if(all_one[i])continue;
int maxx=0;
for(int j=(i-1)*bsz+1;j<=i*bsz;j++)
{
int x=(int)sqrt(a[j]);
sum[i]+=x-a[j],a[j]=x;
maxx=max(maxx,x);
}
if(maxx==1)all_one[i]=true;
}
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
{
int x=(int)sqrt(a[i]);
sum[bel[i]]+=x-a[i],a[i]=x;
}
}

ll get_sum(int l,int r)
{
ll res=0;
for(int i=l;i<=min(r,bel[l]*bsz);i++)
res+=a[i];
if(bel[l]==bel[r])return res;
for(int i=bel[l]+1;i<bel[r];i++)
res+=sum[i];
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
res+=a[i];
return res;
}
}b;


6.单点插入, 查询单点值

struct block
{
static const int __=200005;
static const int _b_=1000;
int a[__];
vector<int>blo[_b_];
int n,bsz,bel[__];

int operator[](int x)
{
int idx=1;
for(;x>blo[idx].size();idx++)
x-=blo[idx].size();
return blo[idx][x-1];
}

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
blo[bel[i]=(i-1)/bsz+1].pb(a[i]);
}

void rebuild()
{
n=0;
for(int i=1;blo[i].size();blo[i++].clear())
for(int j=0;j<blo[i].size();j++)
a[++n]=blo[i][j];
build();
}

void insrt(int x,int val)
{
int idx=1;
for(;x>blo[idx].size();idx++)
x-=blo[idx].size();
blo[idx].insert(blo[idx].begin()+x-1,val);
if(blo[idx].size()>bsz*17)
rebuild();
}

}b;


7.区间加法.乘法, 查询单点值

struct block
{
static const int __=100005;
static const int _b_=400;
ll a[__],ad[_b_],mu[_b_];
int n,bsz,bel[__];

ll operator[](int x){return (a[x]*mu[bel[x]]+ad[bel[x]]);}

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/bsz+1;
for(int i=1;i<=bel
;i++)
mu[i]=1,ad[i]=0;
}

void pushdown(int x)
{
if(mu[x]==1 && ad[x]==0)return;
for(int i=(x-1)*bsz+1;i<=x*bsz;i++)
a[i]=(a[i]*mu[x]+ad[x])%10007;
mu[x]=1,ad[x]=0;
}

void add(int l,int r,ll val)
{
pushdown(bel[l]);
for(int i=l;i<=min(r,bel[l]*bsz);i++)
a[i]=(a[i]+val)%10007;
if(bel[l]==bel[r])return;
for(int i=bel[l]+1;i<bel[r];i++)
ad[i]=(ad[i]+val)%10007;
pushdown(bel[r]);
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
a[i]=(a[i]+val)%10007;
}

void mul(int l,int r,ll val)
{
pushdown(bel[l]);
for(int i=l;i<=min(r,bel[l]*bsz);i++)
a[i]=a[i]*val%10007;
if(bel[l]==bel[r])return;
for(int i=bel[l]+1;i<bel[r];i++)
mu[i]=mu[i]*val%10007,
ad[i]=ad[i]*val%10007;
pushdown(bel[r]);
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
a[i]=a[i]*val%10007;
}
}b;


8.区间覆盖, 查询区间内等于某个数的个数

struct block
{
static const int __=100005;
static const int _b_=400;
ll a[__],st[_b_];
bool same[_b_];
int n,bsz,bel[__];

void build()
{
bsz=(int)sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/bsz+1;
}

void pushdown(int x)
{
if(!same[x])return;
int r=(bel
==x)?n:(x*bsz);
for(int i=(x-1)*bsz+1;i<=r;i++)
a[i]=st[x];
same[x]=false;
}

int set(int l,int r,ll val)
{
int res=0;
pushdown(bel[l]);
for(int i=l;i<=min(r,bel[l]*bsz);i++)
if(a[i]==val)res++;
else a[i]=val;
if(bel[l]==bel[r])return res;
for(int i=bel[l]+1;i<bel[r];i++)
if(same[i])
if(st[i]==val)res+=bsz;
else st[i]=val;
else
{
for(int j=(i-1)*bsz+1;j<=i*bsz;j++)
if(a[j]==val)res++;
else a[j]=val;
same[i]=true,st[i]=val;
}
pushdown(bel[r]);
for(int i=(bel[r]-1)*bsz+1;i<=r;i++)
if(a[i]==val)res++;
else a[i]=val;
return res;
}
}b;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分块