分块 简单的

分块

分块是啥? 暴力?
以前看分块看了一半,放在那里了,,今天想起来了,就又看了一下
分块的思想:把n分成根号n块然后暴力,
这也没啥,主要是记录一下
大段: 被分成的块 一大块
假设要维护的区间是 l~r 把在这个区间里的大段区间暴力维护一下,把两旁的不是一整段的小段暴力维护就好。
时间复杂度:根号n
例题:acwing 243
题目是 给出一个数组 两种操作:
Q l r 查询l~r的区间和
C l r x 把l~r区间里的数都加x
为什么不用线段树?树状数组?
因为我在学分块hhhhh
以下代码
代码:
代码下面有解析
粗心使人心态崩 ——我说的

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;
ll a[maxn];
ll sum[maxn];
ll add[maxn];
int nl[maxn];
int nr[maxn];
int vis[maxn];

void update(int l,int r,ll x)
{
	int pl = vis[l];
	int pr = vis[r];
	if(pl == pr)
	{
		for (int i = l; i <= r; i ++ )
		{
			a[i] += x;
		}
		sum[pl] += x * (r - l + 1);
		return;
	}
	for (int i = pl + 1; i < pr ; i ++ )
	{
		sum[i] += x * (nr[i] - nl[i] + 1);
		add[i] += x;
	}
	for (int i = l; i <= nr[pl]; i ++ )
	{
		a[i] += x;
	}
	sum[pl] += (nr[pl] - l + 1) * x;
	for (int i = nl[pr]; i <= r; i ++ )
	{
		a[i] += x;
	}
	sum[pr] += (r - nl[pr] + 1) * x;
}
ll query(int l,int r)
{
	int pl = vis[l];
	int pr = vis[r];
	ll ans = 0;
	if(pl == pr)
	{
		for (int i = l; i <= r; i ++ )
		{
			ans += a[i];
		}
		ans += add[pl]* (r- l + 1);
		return ans;
	}
	for (int i = pl + 1; i < pr; i ++ )
	{
		ans += sum[i];
	}
	for (int i = l; i <= nr[pl]; i ++ )
	{
		ans += a[i];
	}
	ans += add[pl] * (nr[pl] - l + 1);
	for (int i = nl[pr]; i <= r; i ++ )
	{
		ans +=a[i];
	}
	ans += add[pr]*(r - nl[pr] + 1);
	return ans ;
}

int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n; i ++ )
	{
		scanf("%lld",&a[i]);
	}
	int t = sqrt(n);
	for (int i = 1; i <= t; i ++ )
	{
		nl[i] = (i-1)*t+1;
		nr[i] = i*t;
	}
	if(nr[t] != n)
	{
		nr[t+1] = n;
		nl[t+1] = nr[t]+1;
		t++;
	}
	for (int i = 1; i <= t; i++ )
	{
		for (int j = nl[i]; j <= nr[i]; j ++ )
		{
			vis[j] = i;
			sum[i] += a[j];
		}
	}
	while( m -- )
	{
		char t[2];
		int l,r;
		ll x;
		scanf("%s",t);
		if(t[0] == 'Q')
		{
			scanf("%d%d",&l,&r);
			ll ans = query(l,r);
			printf("%lld\n",ans);
		}
		else
		{
			scanf("%d%d%lld",&l,&r,&x);
			update(l,r,x);
		}
	}
}

下面两边的意思是l~r区间里没有被完全包括的点

add:这个区间的增量,为什么要记录这个?直接加到sum里了呀? 这是我刚开始的问题,因为算两边的时候得把a[i]加上再加上add里的。add里记录的是这整个区间一起加的值修改两边的时候不用改add

a:原数组,修改的时候a数组里只修改两边的

sum:这个块里的和记得改两边得时候也要修改,

怎么感觉我表达的不清楚,好费劲,打扰了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值