玄关-简单可爱小分块
查看原帖
玄关-简单可爱小分块
750476
Hf_Poem楼主2024/10/20 18:55
#include<bits/stdc++.h>
#define setp(a) fixed<<setprecision(a)
#define Venti cout<<endl<<"Venti!"<<endl
#define int long long
#define il inline
using namespace std;
const int V=1e6+10;
int n,m,a[V];
int len,tot,l[V],r[V],sum[V],bel[V],pre[V],add[V];
il void init(void){
	len=sqrt(n),tot=(n-1)/len+1;
	for(int i=1;i<=tot;i++)
		l[i]=r[i-1]+1,r[i]=len*i;
	r[tot]=n;
	for(int i=1;i<=tot;i++){
		for(int j=l[i];j<=r[i];j++)
			bel[j]=i,sum[i]+=a[j];
		pre[i]=pre[i-1]+sum[i];
	}
}

il void modify(int lx,int rx,int x){
	int p=bel[lx],q=bel[rx];
	if(p==q){
		for(int i=lx;i<=rx;i++)
			a[i]+=x,sum[p]+=x;
		for(int i=p;i<=tot;i++) 
			pre[i]=pre[i-1]+sum[i];
		return;
	}
	for(int i=lx;i<=r[p];i++) a[i]+=x,sum[p]+=x;
	for(int i=l[q];i<=rx;i++) a[i]+=x,sum[p]+=x;
	for(int i=p+1;i<=q-1;i++) 
		add[i]+=x,sum[i]+=(r[i]-l[i]+1)*x;
	for(int i=p;i<=tot;i++) 
			pre[i]=pre[i-1]+sum[i];
}

il int query(int lx,int rx){
	int ans=0,p=bel[lx],q=bel[rx];
	if(p==q){
		for(int i=lx;i<=rx;i++)
			ans+=a[i]+add[p];
		return ans;
	}
	ans+=pre[q-1]-pre[p];
	for(int i=lx;i<=r[p];i++) ans+=a[i]+add[p];
	for(int i=l[q];i<=rx;i++) ans+=a[i]+add[q];
	for(int i=p+1;i<=q-1;i++) ans+=sum[i];
	return ans;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	init();
	while(m--){
		int op,x,y,val;
		cin>>op;
		if(op==1){
			cin>>x>>y>>val;
			modify(x,y,val);
		}
		else{
			cin>>x>>y;
			cout<<query(x,y)<<"\n";
		}
	}
	cout<<endl;
	return 0;
}
/*

*/

球挑啊

(我是怎么做到树状数组1和线段树1都挂的找不出问题贴板子求助的

2024/10/20 18:55
加载中...