分块求调 0pts,玄关,有注释
查看原帖
分块求调 0pts,玄关,有注释
737219
YONEX楼主2024/9/28 16:19

拜谢

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
ll k[500005];int m,n,p;ll a,b,c,ans=0;
int add[500007],pos[500007]/*判断点属于哪一个块*/;
ll sum[500007];
int line_l[500007],line_r[500007];
inline long long read()
{
	char cc=getchar();long long f=1,ans=0;
	while(cc<'0' or cc>'9'){if(cc=='-')f=-1;cc=getchar();}
	while(cc>='0' and cc<='9'){ans=(ans*10)+(cc-'0');cc=getchar();}
	return f*ans;
}
inline void  reads(){n=read();m=read();for(int i=1;i<=n;i++)k[i]=read();}
inline void build()
{
	int t=sqrt(n);//块的个数 
	for(int i=1;i<=t;i++){line_l[i]=(i-1)*t+1;line_r[i]=i*t;}//设置左右边界 
	if(line_r[t]<=n){t++;line_l[t]=line_r[t-1]+1;line_r[t]=n;}//特判最后一个块不完整 
	for(int i=1;i<=t;i++)//初始化区间加值和这个点属于那个块
	for(int j=line_l[i];j<=line_r[i];j++){pos[j]=i;sum[i]+=k[j];} 
}
inline void change_point(){a=read();b=read();k[a]+=b;sum[pos[a]]+=b;} 
inline void change_line()
{ 
	a=read();b=read();c=read();
	if(pos[a]==pos[b]){for(int i=a;i<=b;i++)ans+=k[i];printf("%lld\n",ans);return ;} 
	for(int i=pos[a]+1;i<=pos[b]-1;i++)sum[i]+=c*sqrt(n);
	for(int i=a;i<=line_r[pos[a]];i++)add[i]+=c;
	for(int i=line_l[pos[b]];i<=b;i++)add[i]+=c;
//	for(int i=1;i<=n;i++)printf("%d\n",add[i]);printf("\n");
//	printf("%lld\n",ans);return ;
} 
inline void ask_line() 
{ 
	a=read();b=read();ans=0;
	if(pos[a]==pos[b]){for(int i=a;i<=b;i++)ans+=k[i],ans+=add[i];printf("%d\n",ans);return ;} 
	if(a==1 or pos[a-1]!=pos[a]) //左端点不延续 
	{ 
		if(pos[b]==n or pos[b+1]!=pos[b]) //右端点不延续 
		{  
			for(int i=pos[a];i<=pos[b];i++)ans+=sum[i];
			for(int i=a;i<=line_r[pos[a]];i++)ans+=add[i];
			for(int i=line_l[pos[b]];i<=b;i++)ans+=add[i];
		}  
		if(pos[b]!=n and pos[b+1]==pos[b]) //右端点延续 
		{ 
			for(int i=pos[a];i<=pos[b]-1;i++)ans+=sum[i];
			for(int i=a;i<=line_r[pos[a]];i++)ans+=add[i];
			for(int i=line_l[pos[b]];i<=b;i++)ans+=add[i];
		} 
	}  
	if(pos[a-1]==pos[a])//左端点延续 
	{ 
		if(pos[b]!=n and pos[b+1]==pos[b])//右端点延续 
		{ 
			for(int i=pos[a]+1;i<=pos[b]-1;i++)ans+=sum[i];
			for(int i=a;i<=line_r[pos[a]];i++)ans+=k[i],ans+=add[i];
			for(int i=line_l[pos[b]];i<=b;i++)ans+=k[i],ans+=add[i];
		} 
		if(pos[b]!=n and pos[b+1]!=pos[b])//右端点不延续 
		{ 
			for(int i=pos[a]+1;i<=pos[b];i++)ans+=sum[i];
			for(int i=a;i<=line_r[pos[a]];i++)ans+=k[i],ans+=add[i];
//			for(int i=line_l[pos[b]];i<=b;i++)ans+=add[i];
		} 
	} 
//	for(int i=pos[a]+1;i<=pos[b]-1;i++)ans+=sum[i];
//	for(int i=a;i<=line_r[pos[a]];i++)ans+=k[i],ans+=add[i];
//	for(int i=line_l[pos[b]];i<=b;i++)ans+=k[i],ans+=add[i];
	printf("%lld\n",ans);return ;
}  
inline void ask_point(){b=read();printf("%lld\n",k[b]+add[pos[b]]);} 
inline void main_d() 
{reads();build();for(int i=1;i<=m;i++){ans=0;p=read();if(p==1){change_line();continue;}ask_line();}}
int main(){main_d();return 0;}
2024/9/28 16:19
加载中...