【模板整合计划】高阶数据结构—分块

【模板整合计划】高阶数据结构—分块


一:【区间修改(+),单点查询】

数列分块入门 \(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));
    }
}
posted @ 2019-10-27 21:20  辰星凌  阅读(500)  评论(0编辑  收藏  举报