【模板整合计划】高阶数据结构—分块
【模板整合计划】高阶数据结构—分块
一:【区间修改(+),单点查询】
数列分块入门 \(1\) \(\text{[Loj6277]}\)
#include<cstdio>
#include<cmath>
#define LL long long
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
const int N=5e4+3,T=230;
int n,t,x,l,r,Q,fu,pt[N],L[T],R[T];LL a[N],S[T],add[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline void change(Re l,Re r,Re x){
Re p=pt[l],q=pt[r];
if(p==q){F(i,l,r)a[i]+=x;S[p]+=x*(r-l+1);}
else{
F(i,p+1,q-1)add[i]+=x;
F(i,l,R[p])a[i]+=x;S[p]+=x*(R[p]-l+1);
F(i,L[q],r)a[i]+=x;S[q]+=x*(r-L[q]+1);
}
}
inline LL ask(Re x){return a[x]+add[pt[x]];}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1;
F(i,1,n)in(x),a[i]=x;
F(i,1,t)F(j,L[i],R[i])pt[j]=i,S[i]+=a[j];
while(Q--){
in(n),in(l),in(r),in(x);
if(n)printf("%lld\n",ask(r));
else change(l,r,x);
}
}
二:【区间修改(+),区间查询(小于 c 的个数)】
数列分块入门 \(2\) \(\text{[Loj6278]}\)
#include<algorithm>
#include<cstdio>
#include<cmath>
#define LL long long
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
#define lo(l,r,x) (lower_bound(b+l,b+r+1,x)-b)
using namespace std;
const int N=5e4+3,T=230;
int n,t,x,l,r,o,Q,fu,pt[N],L[T],R[T];LL a[N],b[N],add[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline void sak(Re l,Re r,Re p,Re x){F(i,l,r)a[i]+=x;F(i,L[p],R[p])b[i]=a[i];sort(b+L[p],b+R[p]+1);}
inline void change(Re l,Re r,Re x){
Re p=pt[l],q=pt[r];
if(p==q)sak(l,r,p,x);
else{
F(i,p+1,q-1)add[i]+=x;
sak(l,R[p],p,x),sak(L[q],r,q,x);
}
}
inline LL ask(Re l,Re r,LL x){
Re p=pt[l],q=pt[r];LL ans=0;
if(p==q){F(i,l,r)ans+=a[i]+add[p]<x;return ans;}
else{
F(i,p+1,q-1)ans+=lo(L[i],R[i],x-add[i])-L[i];
F(i,l,R[p])ans+=a[i]+add[p]<x;
F(i,L[q],r)ans+=a[i]+add[q]<x;
}
return ans;
}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1;
F(i,1,n)in(x),a[i]=b[i]=x;
F(i,1,t)F(j,L[i],R[i])pt[j]=i;
F(i,1,t)sort(b+L[i],b+R[i]+1);
while(Q--){
in(o),in(l),in(r),in(x);
if(o)printf("%lld\n",ask(l,r,(LL)x*x));
else change(l,r,x);
}
}
三:【区间修改(+),区间查询(x 的前驱)】
数列分块入门 \(3\) \(\text{[Loj6279]}\)
#include<algorithm>
#include<cstdio>
#include<cmath>
#define inf -2147483647
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
using namespace std;
const int N=1e5+3,T=330;
int n,t,x,l,r,o,Q,fu,pt[N],L[T],R[T],a[N],b[N],add[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline void sak(Re l,Re r,Re p,Re x){F(i,l,r)a[i]+=x;F(i,L[p],R[p])b[i]=a[i];sort(b+L[p],b+R[p]+1);}
inline void change(Re l,Re r,Re x){
Re p=pt[l],q=pt[r];
if(p==q)sak(l,r,p,x);
else{
F(i,p+1,q-1)add[i]+=x;
sak(l,R[p],p,x),sak(L[q],r,q,x);
}
}
inline int ask(Re l,Re r,Re x){
Re p=pt[l],q=pt[r],ans=inf,w;
if(p==q){F(i,l,r)if(a[i]+add[p]<x)ans=max(ans,a[i]+add[p]);}
else{
F(i,p+1,q-1)w=lower_bound(b+L[i],b+R[i]+1,x-add[i])-(b+1),ans=w>=L[i]?max(ans,b[w]+add[i]):ans;
F(i,l,R[p])if(a[i]+add[p]<x)ans=max(ans,a[i]+add[p]);
F(i,L[q],r)if(a[i]+add[q]<x)ans=max(ans,a[i]+add[q]);
}
return ans==inf?-1:ans;
}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1;
F(i,1,n)in(x),a[i]=b[i]=x;
F(i,1,t)F(j,L[i],R[i])pt[j]=i;
F(i,1,t)sort(b+L[i],b+R[i]+1);
while(Q--){
in(o),in(l),in(r),in(x);
if(o)printf("%d\n",ask(l,r,x));
else change(l,r,x);
}
}
四:【区间修改(+),区间查询(Sum)】
数列分块入门 \(4\) \(\text{[Loj6280]}\)
#include<cstdio>
#include<cmath>
#define LL long long
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
const int N=5e4+3,T=230;
int n,t,x,l,r,Q,fu,pt[N],L[T],R[T];LL a[N],S[T],add[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline void change(Re l,Re r,Re x){
Re p=pt[l],q=pt[r];
if(p==q){F(i,l,r)a[i]+=x;S[p]+=(LL)x*(r-l+1);}
else{
F(i,p+1,q-1)add[i]+=x;
F(i,l,R[p])a[i]+=x;S[p]+=(LL)x*(R[p]-l+1);
F(i,L[q],r)a[i]+=x;S[q]+=(LL)x*(r-L[q]+1);
}
}
inline LL ask(Re l,Re r){
Re p=pt[l],q=pt[r];LL ans=0;
if(p==q){F(i,l,r)ans+=a[i];ans+=add[p]*(r-l+1);}
else{
F(i,p+1,q-1)ans+=S[i]+add[i]*(LL)(R[i]-L[i]+1);
F(i,l,R[p])ans+=a[i];ans+=add[p]*(LL)(R[p]-l+1);
F(i,L[q],r)ans+=a[i];ans+=add[q]*(LL)(r-L[q]+1);
}
return ans;
}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1;
F(i,1,n)in(x),a[i]=x;
F(i,1,t)F(j,L[i],R[i])pt[j]=i,S[i]+=a[j];
while(Q--){
in(n),in(l),in(r),in(x);
if(n)printf("%lld\n",ask(l,r)%(x+1));
else change(l,r,x);
}
}
五:【区间修改(sqrt),区间查询(Sum)】
数列分块入门 \(5\) \(\text{[Loj6281]}\)
#include<cstdio>
#include<cmath>
#define LL long long
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
const int N=5e4+3,T=230;
int n,t,x,l,r,Q,fu,pt[N],L[T],R[T],pan[T];LL a[N],S[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline void sakura(Re p){
if(pan[p])return;pan[p]=1,S[p]=0;
F(i,L[p],R[p])S[p]+=(a[i]=sqrt(a[i])),pan[p]&=(a[i]<=1);
}
inline void change(Re l,Re r){
Re p=pt[l],q=pt[r];
if(p==q){F(i,l,r)S[p]-=a[i],a[i]=sqrt(a[i]),S[p]+=a[i];}
else{
F(i,p+1,q-1)sakura(i);
F(i,l,R[p])S[p]-=a[i],a[i]=sqrt(a[i]),S[p]+=a[i];
F(i,L[q],r)S[q]-=a[i],a[i]=sqrt(a[i]),S[q]+=a[i];
}
}
inline LL ask(Re l,Re r){
Re p=pt[l],q=pt[r];LL ans=0;
if(p==q){F(i,l,r)ans+=a[i];}
else{
F(i,p+1,q-1)ans+=S[i];
F(i,l,R[p])ans+=a[i];
F(i,L[q],r)ans+=a[i];
}
return ans;
}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1;
F(i,1,n)in(x),a[i]=x;
F(i,1,t)F(j,L[i],R[i])pt[j]=i,S[i]+=a[j];
while(Q--){
in(n),in(l),in(r),in(x);
if(n)printf("%lld\n",ask(l,r));
else change(l,r);
}
}
六:【单点插入,单点查询】
数列分块入门 \(6\) \(\text{[Loj6282]}\)
#include<vector>
#include<cstdio>
#include<cmath>
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
using namespace std;
const int N=1e5+3,T=330;
int n,o,t,x,l,r,Q,fu,pt[N],pw[N],L[T],R[T];
vector<int>a[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline void change(Re w,Re x){
F(i,1,t)
if(w>a[i].size())w-=a[i].size();
else{a[i].insert(a[i].begin()+w-1,x);return;}
}
inline int ask(Re w){
F(i,1,t)
if(w>a[i].size())w-=a[i].size();
else return a[i][w-1];
}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1;
F(i,1,t){F(j,L[i],R[i])in(x),a[i].push_back(x),pt[j]=i;}
while(Q--){
in(o),in(l),in(r),in(x);
if(o)printf("%d\n",ask(r));
else change(l,r);
}
}
七:【区间修改(+,×),区间查询(Sum)】
数列分块入门 \(7\) \(\text{[Loj6283]}\)
#include<cstdio>
#include<cmath>
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
const int N=1e5+3,T=320;
int n,t,x,l,r,Q,fu,P=10007,pt[N],L[T],R[T],a[N],add[T],mul[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline void spread(Re p){
F(i,L[p],R[p])(((a[i]*=mul[p])%=P)+=add[p])%=P;
add[p]=0,mul[p]=1;
}
inline void change(Re l,Re r,Re x){
Re p=pt[l],q=pt[r];spread(p);
if(p==q)F(i,l,r)(a[i]+=x)%=P;
else{
spread(q);
F(i,p+1,q-1)(add[i]+=x)%P;
F(i,l,R[p])(a[i]+=x)%=P;
F(i,L[q],r)(a[i]+=x)%=P;
}
}
inline void change2(Re l,Re r,Re x){
Re p=pt[l],q=pt[r];spread(p);
if(p==q)F(i,l,r)(a[i]*=x)%=P;
else{
spread(q);
F(i,p+1,q-1)(add[i]*=x)%=P,(mul[i]*=x)%=P;
F(i,l,R[p])(a[i]*=x)%=P;
F(i,L[q],r)(a[i]*=x)%=P;
}
}
inline int ask(Re x){return (a[x]*mul[pt[x]]%P+add[pt[x]])%P;}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t,mul[i]=1;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1,mul[t]=1;
F(i,1,n)in(a[i]);
F(i,1,t)F(j,L[i],R[i])pt[j]=i;
while(Q--){
in(n),in(l),in(r),in(x);
if(n>1)printf("%d\n",ask(r));
else n?change2(l,r,x%P):change(l,r,x%P);
}
}
八:【区间修改(推平),区间查询(c的个数)】
数列分块入门 \(8\) \(\text{[Loj6284]}\)
这道题疯狂 \(\text{TLE}\),死活过不了。。。
#include<cstdio>
#include<cmath>
#define Re register int
#define F(x,a,b) for(Re x=a;x<=b;++x)
const int N=1e5+3,T=330;
int n,t,x,l,r,Q,fu,pt[N],L[T],R[T],a[N],tag[T];
inline void in(Re &x){
x=fu=0;char c=getchar();
while(c<'0'||c>'9')fu|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=fu?-x:x;
}
inline int sak(Re l,Re r,Re p,Re x){
Re tmp=0;
if(tag[p]!=-1){F(i,L[p],R[p])a[i]=tag[p];tmp+=(r-l+1)*(tag[p]==x);}
else F(i,l,r)tmp+=a[i]==x;
tag[p]=-1;F(i,l,r)a[i]=x;
return tmp;
}
inline int fuck(Re p,Re x){
Re tmp=0;
if(tag[p]!=-1){F(j,L[p],R[p])a[j]=tag[p];tmp+=(R[p]-L[p]+1)*(tag[p]==x);}
else F(j,L[p],R[p])tmp+=a[j]==x;
tag[p]=x;
return tmp;
}
inline int sovle(Re l,Re r,Re x){
Re p=pt[l],q=pt[r],ans=0;
if(p==q)return l==r?fuck(p,x):sak(l,r,p,x);
else{
F(i,p+1,q-1)ans+=fuck(i,x);
ans+=sak(l,R[p],p,x)+sak(L[q],r,q,x);
}
return ans;
}
int main(){
in(n),t=sqrt(Q=n);
F(i,1,t)L[i]=(i-1)*t+1,R[i]=i*t;
if(R[t]<n)R[++t]=n,L[t]=R[t-1]+1;
F(i,1,n)in(x),a[i]=x;
F(i,1,t){tag[i]=-1;F(j,L[i],R[i])pt[j]=i;}
while(Q--){
in(l),in(r),in(x);
printf("%d\n",sovle(l,r,x));
}
}