差分数组简介

 

定义:

      记录当前位置的数与上一位置的数的差值。

举个例子:

可以发现∑ b[j](j = 1 to i)即代表a[i] 的值. (∑ 即代表累加.)

我们可能认为这是前缀和,实际上这并不是真正意义上的前缀和.

前缀和的思想是 根据元素与元素之间的并集关系(和的关系),求出某些元素的和的值.对应的为∑ a[j](j = 1 to i)

而差分的思想与此不同.

差分的思想是 根据元素与元素之间的逻辑关系(大小关系),求出某一位置元素的值.对应的为∑ b[j](j = 1 to i)

用途:

1. 快速处理区间加减操作:O(1)。

2. 询问区间和:O(n)处理O(1)查询。

m次操作,每一次操作,给定l,r,del.将l~r区间的所有数增加del;

最后有q个询问,给你 l,r ,每一次询问求出l~r的区间和。

PS: 先进行m个修改操作,后进行查询操作.

考虑我们差分数组记录的是什么,它记录的是当前位置的数与上一个数的差值.

如果我们在差分数组的 b_x减去del 在b_{y+1}位置处加上del,就能达到整个区间修改的操作.

还是刚开始的栗子.

这样是不是达到了区间修改操作,是不是! "是!,tql!!"

这样我们就能做到O(1)修改啦!

我们再定义两个数组(先不要忘记我们的差分数组为b_i

s_i代表∑ b[j](j = 1 to i) (其实就是代表a[i] qwq

sum_i代表∑ s[j](j = 1 to i) 即代表前缀和. qwq

容易发现的是 sum_r -sum_{l-1}=∑ s[j](j = 1 to i)

什么不理解为什么是l-1?

那我们把式子展开看 qwq

emmmm 差点跑去讲前缀和

所以说我们可以在修改操作完成之后,O(n)的计算我们的sum数组,然后在询问的时候O(1)的输出了.

具体这个题的代码是这样的↓

例题

HDU-6273

法一:差分数组区间修改加查询。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 100;
ll a[1000001];
ll b[1000001];
ll mod=998244353;
ll qpow(ll a,ll b)
{
	ll res=1;
	while(b)
	{
		if(b&1)
		{
			res=(res%mod*a%mod)%mod;
		}
		a=a%mod*a%mod;
		b>>=1;
	}
	return res%mod;
}
int main()
{
	int t;
	int n,m;
	cin>>t;
	while(t--)
	{
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		cin>>n>>m;
		int l,r,x;
		while(m--)
		{
			cin>>l>>r>>x;
			if(x==2)
			{
				a[l]++;//差分数组记录2的次数
				a[r+1]--;
			}
			else
			{
				b[l]++;//记录3的次数
				b[r+1]--;
			}
		}
		ll min1=a[1];
		ll min2=b[1];
		for(int i=2; i<=n; i++)
		{
			a[i]+=a[i-1];//维护区间最小值
			b[i]+=b[i-1];
			min1=min(a[i],min1);
			min2=min(b[i],min2);
		}
		min1=qpow(2,min1)%mod;
		min2=qpow(3,min2)%mod;
		ll res=(min1*min2)%mod;
		cout<<res<<endl;
	}
	return 0;
}

 

法二线段树:

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值