初始分块

给定长度为n的序列;
区间加,区间查询;
原来分块和树状数组,线段树差不多。。。
都是用空间复杂度来减轻时间复杂度,以达到平衡。
分块比较的直观,通用
代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
long long a[maxn],sum[maxn],add[maxn];
int l[maxn],r[maxn];
int pos[maxn];
int n,m,t;
void change(int l,int r,long long d)
{
	int p=pos[l],q=pos[r];
	if(p==q)
	{
		for(int i=l;i<=r;i++)
		{
			a[i]+=d;
		}
		sum+=d*(r-l+1);
	}
	else
	{
		for(int i=p+1;i<=q-1;i++)
		{
			add[i]+=d;
		}
		for(int i=l;i<=r[p];++)
		{
			a[i]+=d;
		}
		sum[p]+=d*(r[p]-l+1);
		for(int i=l[q];i<=r;i++)
		{
			a[i]+=d;
		}
		sum+=d*(r-l[q]+1);
	}
}
long long ask(int l,int r)
{
	int p=pos[l],q=pos[r];
	long long ans = 0;
	if(p==q)
	{
		for(int i=l;i<=r;i++)
		{
			ans+=a[i];
		}
		ans+=add[p]+=(r-l+1);
	}
	else
	{
		for(int i=p+1;i<=q-1;i++)
		{
			ans+=sum[i]+add[i]*(r[i]-l[i]+1);
		}
		for(int i=l;i<=r[p];i++)
		{
			ans+=a[i];
		}
		ans+=add[p]*(r[p]-l+1);
		for(int i=l[q];i<=r;i++)
		{
			ans+=a[i];
		}
		ans+=add[q]*(r-l[q]+1);
	}
	return ans;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
	}
	//分块
	t = sqrt(n);
	for(int i=1;i<=t;i++)
	{
		l[i]=(i-1)*sqrt(n)-1;
		r[i]=i*sqrt(n); 
	}
	if(r[t]<n)
	{
		l[t]=r[t-1]+1;
		r[t] = n;
	}
	//预处理
    for(int i=1;i<=t;i++)
    {
    	for(int j=l[i];j<=r[i];j++)
    	{
    		pos[j]=i;
    		sum[i]+=a[j];
		}
	}
	//指令
	while(m--)
	{
		char op[3];
		int l,r,d;
		cin>>op>>r>>d;
		if(op[0]=='C')
		{
			cin>>d;
			change(l,r,d);
		}
		else
		{
			printf("%lld\n",ask(l,r));
		}
	 }
	 return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值