差分数组这样的优化表示方法(在我们日常生活中)十分常见
如果我们假设有一列数a[1],a[2],a[3]...
那么若这样的差分数组表示为d[1],d[2],d[3]...
则有d[1]=a[1]; //一般我们也可以假设一个a[0]=0,就可以和下面的一样了
d[2]=a[2]-a[1];
d[3]=a[3]-a[2];
...
差分数组应用很多,不过大部分都需要具体题目具体分析
但是在区间修改的离线查询中,差分数组是一个很优秀的线性算法
E.G. 题目描述链接
宾馆房间 hotelroom (这里题目描述我就简略了写了)
2180年奥运会竞技类分会场,将在XX市举行。会场自然是政府的事情,我们就别操心了。艾瑞克却被兴奋而苦恼的情绪折磨着,他的宾馆是XX市最好的宾馆,近期旅客投宿的订单m份接踵而至,时间从1~n天,这代表着大把大把的银子,可是他最多只能提供k间客房,更多的他只能提前去租附近的房子并赶紧装修一下,时间很紧啊。
艾瑞克找到了他最好的朋友你:“哪,这是所有的订单,你给我在1s内计算出最高峰时,超出多少间客房,这样我才能知道得去租多少房子啊。”
每张订单包含dj,sj,tj:表示从第sj日至第tj日,预定房间dj间。
【输入描述】:
第一行包含两个正整数n,m,k,表示天数、订单的数量,和现有客房数。
接下来有m行,每行包含三个正整数dj,sj,tj,表示租借的数量,租借开始、结束分别在第几天。
每行相邻的两个数之间均用一个空格隔开。天数与订单均用从1开始的整数编号。
【输出描述】:
只有一个整数,表示最高峰时还差多少客房,客房足够输出0(骗不到分)。
【样例输入】:
4 3 6
2 1 3
3 2 4
4 2 4
【样例输出】
3
【数据范围及描述】:
1<=n,m<=1000,000;1<=sj<=tj<=n;1<=k,dj<=1000
下面讲解原理:
(1)
我们设sum[i]为d[i]的前缀和
那么显然sun[i]=a[i]
(2)
在区间修改的时候如果我们直接对整个区间进行操作,那么复杂度将会非常高
当然我们可以使用线段树等工具来优化,但是还是很慢
那如果有机会每一次修改的时候都只改单个数据(或两个数据),那该有多好?
所以,如果我们需要在[l,r]中都加上x的话
只需要d[l]+=x,d[r+1]-=x;
//(自己想想为什么)
然后这道题就迎刃而解了
我们只需要每一次修改时对d数组处理两次,然后最后查询的时候先用d[]把a[]算出来,最后直接离线O(1)查询
代码片段:
for(int i=1;i<=m;i++){
d=read();s=read();j=read();
a[s]+=d;a[j+1]-=d;
}
for(int i=1;i<=n;i++){
sum+=a[i];
ans=max(ans,sum-k);
}
printf("%d",ans);
//还有就是稍微注意一下读入优化,这种题目当心一点
That‘s all.
原文地址:https://www.cnblogs.com/battlin/p/12243063.html