分块
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;
相关文章推荐
- Codeforces103D Time to Raid Cowavans(分块+离线处理)
- HYSZB PROBLEM B(mobius反演+分块+容斥原理)
- 【BZOJ 2820】 YY的GCD (莫比乌斯+分块)
- [五维偏序 分块 bitset] HihoCoder #1236 2015北京网络赛 J Scores
- 数据结构(分块):[HZOI 2015]easy seq
- [置顶] CodeForces 455D Serega and Fun (分块+双端队列)
- HDU 3333 分块求区间不同数和
- codeforce#378C. Epidemic in Monstropolis(模拟+分块+树状数组)
- python-opencv 图像分块处理
- _bzoj2002 [Hnoi2010]Bounce 弹飞绵羊【分块】
- 网页分块上传文件
- BZOJ 2120: 数颜色 && 2453: 维护队列 【带修莫队版题【也可以学黄学长分块
- Bzoj 1086: [SCOI2005]王室联邦(分块)
- [SD2016集训]Play with array(分块+双向链表)
- [BZOJ4537][Hnoi2016][分块]最小公倍数
- 数据结构复习之分块
- matlab 图像分块及恢复
- [bzoj2002][Hnoi2010]Bounce弹飞绵羊——分块
- CodeChef Chef and Churu [分块]
- 【BZOJ2141】排队 树状数组+分块