分块求调
查看原帖
分块求调
701221
Chr0n1CleC楼主2022/7/15 17:15
#include<stdio.h>
#include<math.h>
#define ll long long
#define N 200009

ll a[N];
ll sum[N];
int st[N];
int en[N];
int len[N];
int whe[N];
ll lazy[N];
int fk = 0;

inline void build(int l, int r)
{
	for (int i = 1;i <= fk;i ++)
		st[i] = en[i - 1] + 1, en[i] = st[i] + fk - 1; 
	en[fk] = r;
	for (int i = 1;i <= fk;i ++)
	{
		len[i] = en[i] - st[i] + 1;
		for (int j = st[i];j <= en[i];j ++)
			sum[i] += a[j], whe[j] = i;
	}
}

inline void plus(int l, int r, int c)
{
	int L = whe[l], R = whe[r];
	if (L == R)
	{
		for (int i = l;i <= r;i ++)
			a[i] += c;
		return;
	}
	for (int i = l;i <= en[L];i ++)
		a[i] += c;
	for (int i = L + 1;i < R;i ++)
		lazy[i] += c;
	for (int i = st[R];i <= r;i ++)
		a[i] += c;
}

inline ll query(int l, int r)
{
	int L = whe[l], R = whe[r];
	ll ret = 0;
	if (L == R)
	{
		for (int i = l;i <= r;i ++)
			ret += lazy[L] + a[i];
		return ret;
	}
	for (int i = l;i <= en[L];i ++)
		ret += lazy[L] + a[i];
	for (int j = L + 1;j < R;j ++)
		ret += sum[j] + lazy[j] * len[j];
	for (int i = st[R];i <= r;i ++)
		ret += lazy[R] + a[i];
	return ret;
}

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1;i <= n;i ++)
		scanf("%d", &a[i]);
	fk = sqrt(n);
	if (n % fk)
		fk ++;
	build(1, n);
	int opt, l, r, c;
	while (m --)
	{
		scanf("%d%d%d", &opt, &l, &r);
		if (opt == 1)
			scanf("%d", &c), plus(l, r, c);
		else
			printf("%lld\n", query(l, r));
	}
	
	return 0;
}
2022/7/15 17:15
加载中...