MnZn 刚学分块 1e-9ms 求助卡常
查看原帖
MnZn 刚学分块 1e-9ms 求助卡常
1268524
DX3906_ourstar楼主2025/7/26 07:35

rt,用线段树写,可以轻松水过;但在相同的思路下用分块,会 TLE on #12

分块代码如下:

#include<iostream>
#include<cmath>
#define ll long long
#define INF 1e18
using namespace std;

const int N=1e5+5;
const int M=320;

namespace OIfast{
	
	char buf[1<<21],*p1,*p2,*top, buffer[1<<21];
	#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?0:*p1++)
	
	inline ll read(){
		ll n=0,f=1;
		char c=getchar();
		while(c<'0'||c>'9'){
			if(c=='-')f=-1;
			c=getchar();
		}
		while(c>='0'&&c<='9'){
			n=(n<<3)+(n<<1)+(c^48);
			c=getchar();
		}
		return n*f;
	}
	
	inline void print(ll n){
		if(n<0)n=~n+1,putchar('-');
		if(n>=10)print(n/10);
		putchar(n%10^48);
		return ;
	}
	
	inline void write(ll n,char c){
		print(n),putchar(c);
		return ;
	}
	
}using namespace OIfast;

//namespace Math{
//	
//	ll gcd(ll a,ll b){
//		ll t=1,c,d;
//		while(a!=b){
//			if(!b)break;
//			if(a<b) swap(a,b);
//			if(!(a&1)){
//				a>>=1;
//				c=1;
//			}else c=0;
//			if(!(b&1)){
//				b>>=1;
//				d=1;
//			}else d=0;
//			if(c&&d) t<<1;
//			else if(!c&&!d)a-=b;
//		}
//		return t*a;
//	}
//	
//	inline ll lcm(ll a,ll b){
//		return a/gcd(a,b)*b;
//	}
//	
//}using namespace Math;

namespace FK{
	
	int n,m;
	int k,tot;
	
	int L[M],R[M];
	short loc[N];
	ll la[M]/*加*/,sum[M],maxx[M];
	ll a[N];
	
	inline void pushdown(int i){
		for(int j=L[i];j<=R[i];++j)a[j]+=la[i];
		la[i]=0;
		return ;
	}
	
	inline void add(int i){
		sum[i]=0;
		for(int j=L[i];j<=R[i];++j)sum[i]+=a[j];
		return ;
	}
	
	inline void modify(int i){
		maxx[i]=-INF;
		for(int j=L[i];j<=R[i];++j)maxx[i]=max(maxx[i],a[j]);
		return ;
	}
	
	inline void init(){
		k=sqrt(n);
		if(k*k<n)tot=k+1;
		else tot=k;
		for(int i=1;i<=tot;++i){
			L[i]=(i-1)*k+1;
			if(i==tot)R[i]=n;
			else R[i]=L[i]+k-1;
			add(i),modify(i);
		}
		return ;
	}
	
	inline void upd1(int tar,ll v){//加
		pushdown(loc[tar]);
		a[tar]=v;
		add(loc[tar]),modify(loc[tar]);
		return ;
	}
	
	inline void upd2(int l,int r,ll v){//模
		if(loc[l]==loc[r]){
			pushdown(loc[l]);
			for(int i=l;i<=r;++i)a[i]%=v;
			add(loc[l]),modify(loc[l]);
		}else{
			pushdown(loc[l]),pushdown(loc[r]);
			for(int i=l;i<=R[loc[l]];++i)a[i]%=v;
			for(int i=L[loc[r]];i<=r;++i)a[i]%=v;
			add(loc[l]),add(loc[r]),modify(loc[l]),modify(loc[r]);
			for(int i=loc[l]+1;i<=loc[r]-1;++i){
				if(maxx[i]<v)continue ;
				pushdown(i);
				for(int j=L[i];j<=R[i];++j)a[j]%=v;
				add(i),modify(i);
			}
		}
		return ;
	}
	
	inline ll qry(int l,int r){
		ll res=0;
		if(loc[l]==loc[r]){
			pushdown(loc[l]);
			for(int i=l;i<=r;++i)res+=a[i];
		}else{
			pushdown(loc[l]),pushdown(loc[r]);
			for(int i=l;i<=R[loc[l]];++i)res+=a[i];
			for(int i=L[loc[r]];i<=r;++i)res+=a[i];
			for(int i=loc[l]+1;i<=loc[r]-1;++i)res+=sum[i];
		}
		return res;
	}
	
}using namespace FK;

inline void work(){
	int op=read(),l=read(),r;
	if(1==2){
		puts("wow");
	}else if(op==1){
		r=read();
		write(qry(l,r),'\n');
	}else if(op==2){
		r=read();
		ll x=read();
		upd2(l,r,x);
	}else if(op==3){
		ll x=read();
		upd1(l,x);
	}
	return ;
}

signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)a[i]=read();
	init();
	while(m--)work();
	return 0;
}

#undef ll
#undef INF
2025/7/26 07:35
加载中...