分块 TLE 70分 (求算法改进/卡常)
查看原帖
分块 TLE 70分 (求算法改进/卡常)
335552
Christophe_楼主2022/1/30 17:39

RT, 听说分块能过这题(我们老师就过了),但是我写的分块连学校OJ的正解是分块的这一题的弱化版都过不了,所以有些怀疑是哪里写错了,导致复杂度升高:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define int long long 
const int N=1e5+5,M=320+5;
int n,m,P,a[N],st[M],ed[M],p[N],bl,t,mm[M],mp[M],sum[M];
char buf[1<<23],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read() {
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)){ if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
	return x*f;
}
inline void write(int x){        
    if(x<0){ putchar('-'); x=-x; }      
    if(x>9) write(x/10);     
    putchar(x%10+'0');
}
inline void Build(void){
	bl=sqrt(n),t=(n+bl-1)/bl;
	for(int i=1;i<=n;++i){
		p[i]=(i-1)/bl+1;
		if(i<=t){
			st[i]=(i-1)*bl+1,ed[i]=min(i*bl,n),mm[i]=1;
			for(int j=st[i];j<=ed[i];++j) sum[i]=(sum[i]+a[j])%P;
		}
	}	
}
inline void Refresh(int l,int r,int x,int op){
	int pl=p[l];
	if(mm[pl]==1&&mp[pl]==0){
		for(int i=l;i<=r;++i){
			sum[pl]-=a[i];
			if(op==1) a[i]=a[i]*x%P;
			else a[i]=(a[i]+x)%P;
			sum[pl]=(sum[pl]+a[i])%P;			
		}
		return;
	}
	for(int i=st[pl];i<=ed[pl];++i){
		sum[pl]-=a[i],a[i]=(a[i]*mm[pl]+mp[pl])%P;	
		if(i>=l&&i<=r)
			if(op==1) a[i]=a[i]*x%P;
			else a[i]=(a[i]+x)%P;
		sum[pl]=(sum[pl]+a[i])%P;
	}
    mm[pl]=1,mp[pl]=0;
}
inline void Change(int l,int r,int x,int op){
	int pl=p[l],pr=p[r];
	if(pl==pr) Refresh(l,r,x,op);		
	else{
		for(int i=pl+1;i<=pr-1;++i)
			if(op==1) mm[i]=mm[i]*x%P,mp[i]=mp[i]*x%P;
			else mp[i]=(mp[i]+x)%P;
		Refresh(l,ed[pl],x,op),Refresh(st[pr],r,x,op);
	}
}
inline int Query(int l,int r){
	int pl=p[l],pr=p[r],ans=0;
	if(pl==pr) for(int i=l;i<=r;++i) ans=(ans+a[i]*mm[pl]+mp[pl])%P;
	else{
		for(int i=pl+1;i<=pr-1;++i) ans=(ans+sum[i]*mm[i]+bl*mp[i])%P;
		for(int i=l;i<=ed[pl];++i) ans=(ans+a[i]*mm[pl]+mp[pl])%P;
		for(int i=st[pr];i<=r;++i) ans=(ans+a[i]*mm[pr]+mp[pr])%P;
	}
	return ans%P;
}
signed main(){
	n=read(),m=read(),P=read();
	for(int i=1;i<=n;++i) a[i]=read();
    Build();
	for(int i=1;i<=m;++i){
		int op=read(),x=read(),y=read(),k;
		if(op==3) write(Query(x,y)),putchar('\n');
		else k=read(),Change(x,y,k,op);
	}
	return 0;
}
2022/1/30 17:39
加载中...