(⊙o⊙)????10r+Orz 求助
查看原帖
(⊙o⊙)????10r+Orz 求助
366430
AndyC楼主2023/3/1 21:20
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxlen=100000+10;
int n,m;
ll size,he[maxlen],cheng[maxlen],jia[maxlen],k,ans,p,a[maxlen];
int kuai[maxlen];
int l[maxlen],r[maxlen];//存每个块的左右边界 
void pushdown(int x){
    for(int i=l[x];i<=r[x];i++)//把这个块里面的都pushdown 
        a[i]=(a[i]*cheng[x]+jia[x])%p;//!!!!!先乘后加!!!!!!! 
    cheng[x]=1;
	jia[x]=0;
}
 
int main(){
	cin>>n>>p; 
	size=sqrt(n);
    for(int i=1;i<=n;i++) kuai[i]=(i-1)/size+1;
    for(int i=n;i>=1;i--) l[kuai[i]]=i;//计算块的左边界
    //本来是左边的 但是后来被右边的盖着了 为了让他可以被盖着 所以从后向前 
    for(int i=1;i<=n;i++) r[kuai[i]]=i;//计算块的右边界
    for(int i=1;i<=n;i++) cin>>a[i];
    cin>>m;
    for(int i=1;i<=n;i++) he[kuai[i]]+=a[i];
    for(int i=1;i<=n;i++) cheng[kuai[i]]=1;
    for(int i=1;i<=m;i++){
    	int opt,x,y;                              
    	cin>>opt>>x>>y;
        if(opt==1){//乘法 
        	cin>>k;
            pushdown(kuai[x]);//加之前和乘之前都需要把delta清零 
            int temp=min(y,r[kuai[x]]);//算出左侧碎块右边界
            for(int j=x;j<=temp;j++){//左侧碎块
                he[kuai[x]]+=(k-1)*a[j]%p;
				a[j]=(a[j]*k)%p;
        	}
        	pushdown(kuai[y]);//重置右侧碎块
            for(int j=y;j>=l[kuai[y]];j--){//将右侧碎块算出
                he[kuai[y]]+=(k-1)*a[j]%p;
				a[j]=a[j]*k%p;
			}
            if(kuai[x]!=kuai[y]){//中间还有完整的块 
            	for(int j=kuai[x]+1;j<=kuai[y]-1;j++){//整块做加法,乘法标记,算出和
                	cheng[j]=cheng[j]*k%p;
					jia[j]=(jia[j]*k)%p;//存delta 
					he[j]=he[j]*k%p;//算和 
				}
            }
        }
        if(opt==2){//加法
        	cin>>k; 
			int t=min(y,r[kuai[x]]);//算出左侧碎块右边界 
			
            pushdown(kuai[x]);//加之前和乘之前都需要把delta清零
			he[kuai[x]]=(he[kuai[x]]+(t-x+1)*k)%p;//和值增加元素数*k
			for(int j=x;j<=t;j++) a[j]=(a[j]+k)%p;//算出左侧碎块每个数
			
			pushdown(kuai[y]);//重置加、乘标记,算出值
            he[kuai[y]]=(he[kuai[y]]+((y-l[kuai[y]]+1)*k))%p;//和值增加元素数*k
            for(int j=y;j>=l[kuai[y]];j--) a[j]=(a[j]+k)%p;

            if(kuai[x]!=kuai[y]){//中间还有完整块 
				for(int j=kuai[x]+1;j<=kuai[y]-1;j++){//整块
                	jia[j]+=k;//加法标记+k
					he[j]=(he[j]+size*k)%p;//和值增加每块元素数*k
				}
            }
        }
        if(opt==3){//查询 但是不pushdown 省时间只算需要的 
            ans=0;
			int t=min(y,r[kuai[x]]);//左侧最碎块边界
            for(int j=x;j<=t;j++){
            	ans+=(a[j]*cheng[kuai[x]]+jia[kuai[x]])%p;//
            	ans%=p;
			}
                
            for(int j=y;j>=l[kuai[y]];j--){
            	ans+=(a[j]*cheng[kuai[y]]+jia[kuai[y]])%p;
            	ans%=p;
			}
                
            if(kuai[x]!=kuai[y]){
				for(int j=kuai[x]+1;j<=kuai[y]-1;j++){//完整块的值 
					ans+=he[j];
					ans%=p;
				}
            }
            cout<<ans%p<<endl;
        }
    }
    return 0;
}

这是用分块写的 然后还用分块写了一个线段树2 模板 几乎跟着提一模一样 P3373

#include<bits/stdc++.h>
using namespace std;

long long size,n,m,opt,he[100100],cheng[100100],jia[100100],k,p,a[100100];
long long kuai[100100],l[100100],r[100100],x,y;
void pushdown(long long x){
	for(long long i=l[x];i<=r[x];i++){
		a[i]=(a[i]*cheng[x]+jia[x])%p;
	}
	cheng[x]=1;
	jia[x]=0;
}
void init(){
	cin>>n>>m>>p;
	size=sqrt(n);
	
	for(long long i=1;i<=n;i++){
		kuai[i]=(i-1)/size + 1;
		
	}
	for(long long i=n;i>=1;i--){
		l[kuai[i]]=i;
	}
	
	for(long long i=1;i<=n;i++){
		r[kuai[i]]=i;
	}
	for(long long i=1;i<=n;i++) cin>>a[i];
	for(long long i=1;i<=n;i++) he[kuai[i]]+=a[i];
	for(long long i=1;i<=n;i++) cheng[kuai[i]]=1;
}
void work(){
	for(long long i=1;i<=m;i++){
		cin>>opt>>x>>y;
		if(opt==1){//乘法 
			//左边碎块pushdown 右边碎块pushdown 中间cheng数组变化就可以了 
			cin>>k;
			long long temp=min(y,r[kuai[x]]);//左块右边界 
			
			pushdown(kuai[x]);
			for(long long j=x;j<=temp;j++){
				he[kuai[x]]+=((k-1)*a[j])%p;
				a[j]=(a[j]*k)%p;
			}
			
			pushdown(kuai[y]);
			for(long long j=y;j>=l[kuai[y]];j--){
				he[kuai[y]]+=((k-1)*a[j])%p;
				a[j]=(a[j]*k)%p;
			}
			
			if(kuai[x]!=kuai[y]){
				for(long long j=kuai[x]+1;j<=kuai[y]-1;j++){
					cheng[j]=cheng[j]*k%p;
					jia[j]=(jia[j]*k)%p;
					he[j]=(he[j]*k)%p;
				}
			}
		}
		else if (opt==2){
			cin>>k;
			long long t=min(y,r[kuai[x]]);
			
			pushdown(kuai[x]);
			
			he[kuai[x]]=(he[kuai[x]]+(t-x+1)*k)%p;
			for(long long j=x;j<=t;j++){
				a[j]=(a[j]+k)%p;
			}
			
			pushdown(kuai[y]);
			
			he[kuai[y]]=(he[kuai[y]]+((y-l[kuai[y]]+1)*k))%p;
			for(long long j=y;j>=l[kuai[y]];j--){
				a[j]=(a[j]+k)%p;
			}
			
			if(kuai[x]!=kuai[y]){
				for(long long j=kuai[x]+1;j<=kuai[y]-1;j++){
					jia[j]+=k;
					he[j]=(he[j]+size*k)%p;
				}
			}
		}
		
		else if (opt==3){
			long long ans=0;
			long long t=min(y,r[kuai[x]]);
			for(long long j=x;j<=t;j++){
				ans+=(a[j]*cheng[kuai[x]]+jia[kuai[x]])%p;
			}
			
			for(long long j=y;j>=l[kuai[y]];j--){
				ans+=(a[j]*cheng[kuai[y]]+jia[kuai[y]])%p;
			}
			
			if(kuai[x]!=kuai[y]){
				for(long long j=kuai[x]+1;j<=kuai[y]-1;j++){
					ans+=he[j];
				}
			}
			ans%=p;
			cout<<ans<<endl;
		}
	}
}
int main(){
	init();
	
	work();
	
	return 0;
}
2023/3/1 21:20
加载中...