差分数组

介绍:

区间修改查询问题一般会想到用线段树或者树状数组来做,但是题目是离线查询,即完成修改后再查询的话,可以用到差分数组

差分数组:

对于数组a[i],我们令d[i]=a[i]-a[i-1]  (特殊的,第一个为d[1]=a[1]),则d[i]为一个差分数组。

我们发现统计d数组的前缀和sum数组,有

sum[i]=d[1]+d[2]+d[3]+...+d[i]=a[1]+a[2]-a[1]+a[3]-a[2]+...+a[i]-a[i-1]=a[i],即前缀和sum[i]=a[i];

因此每次在区间[l,r]增减x只需要令d[l]+x,d[r+1]-x,就可以保证[l,r]增加了x,而对[1,l-1]和[r+1,n]无影响。 复杂度则是O(n)的。

题目:

HDU 1556 Color the ball

题意:

给出一个区间n, n个数初始值都是0, 给出n个区间修改,修改是在[l,r]上加1, 最后输出n个数。

分析:

属于离线查询, 可以维护差分数组来求出最后的数字。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 0x3f3f3f3f
 4 const int N = 100000 + 10;
 5 int m, q;
 6 long long a[N], d[N], sum[N];
 7 int main() {
 8     int n;
 9     while (scanf("%d", &n) && n) {
10         memset(a, 0, sizeof(a));//初始化都为0
11         int l, r;
12         memset(d, 0, sizeof(d));
13         d[1] = a[1];//特殊处理第一个数
14         for (int i = 0; i < n; i++) {
15             scanf("%d%d", &l, &r);
16             d[l] += 1;
17             d[r+1] -= 1;
18         }
19         memset(sum, 0, sizeof(sum));
20         for (int i = 1; i <= n; ++i) {
21             sum[i] = sum[i-1] + d[i]; //求d[i]前缀和, 也就是修改后的a[i]
22         }
23         for (int i = 1; i <= n; ++i){
24             printf("%lld",sum[i]);
25             if(i != n) printf(" ");
26         }
27         puts("");
28     }
29
30     return 0;
31 }

BZOJ 3043 IncDec Sequence

题意:

给定一个长度为n的数列a[i],每次可以选择一个区间[l,r],使这个区间内的数都加一或者都减一。

求:(1)至少需要多少次操作才能使数列中的所有数都一样。

  (2)在保证最少次数的前提下,最终得到的数列有多少种

分析:

因为我们最终是求一个所有数的一样的序列, 所以其差分数组就是除了d[1]外,d[2]~d[n]全为0。

然后题目中区间加一或者区间减一操作, 其实就是在差分数组中, 找出两个下标i, j, d[i]++, d[j]--(或者d[i]--, d[j]++)

所以我们就可以利用这个操作把d[2]~d[n]中的正数和负数中和, 然后还有会一部分正数(或负数)多出来, 我们只需要在这个点上面直接加减就好(这个单点操作其实有两重意义,涉及第二问)

我们求出d[2]~d[n]的正数和绝对值pos, 负数和绝对值neg

所以第一问的答案就是max(pos,neg)

刚刚提到了有一个单点操作的意义, 我们就拿d[i]++来说吧

第一种含义是, 因为d[1]是什么并没有关系, 所以可以代表d[1]-- , d[i]++, 实际意义就是数组a[1]~a[i-1]都减去1。

第二种含义是, 因为修改区间[l,r]加一是在d[l]++, d[r+1]--, 如果这个r等于n的时候, 那么r+1并没有意义, 所以也成了单点操作, 实际意义就是a[i]~a[n]加上1。

就是说那个多出来的d[i]可以配给d[1]或者d[n+1](没有意义)

所以我们的问题二可以转化为d[1]的取值个数, 那么可以配0次, 1次...到abs(pos-neg)次, 所以最终d[1]的取值总共abs(pos-neg) + 1次。

时间: 2024-08-30 02:20:40

差分数组的相关文章

HDU-1556 Color the ball 【差分数组】

Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗? Input 每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <=

[NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组

[NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有星球. 小P掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从ui号星球沿最快的宇航路径飞行到vi号星球去.显然,飞船驶过一条航道是需要时间的,对于航道j,任意飞船驶过它所花费的时间为tj,并且任意两艘飞船之间不会产生任何干扰. 为了鼓励科技创新,L国国王同意小P的物流

浅谈差分数组的原理及简单应用

一.差分数组的定义及用途 1.定义: 对于已知有n个元素的离线数列d,我们可以建立记录它每项与前一项差值的差分数组f:显然,f[1]=d[1]-0=d[1];对于整数i∈[2,n],我们让f[i]=d[i]-d[i-1]. 2.简单性质: (1)计算数列各项的值:观察d[2]=f[1]+f[2]=d[1]+d[2]-d[1]=d[2]可知,数列第i项的值是可以用差分数组的前i项的和计算的,即d[i]=f[i]的前缀和. (2)计算数列每一项的前缀和:第i项的前缀和即为数列前i项的和,那么推导可知

浅谈差分数组的应用(二)&amp;[NOIP2012]借教室题解

[NOIP2012提高&洛谷P1083]借教室 Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样.面对海量租借教室的信息,我们自然希望编程解决这个问题. 我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要

树状数组区间修改,区间更新:差分数组的运用

树状数组最原始的作用就是求前缀和,可以实现单点修改和区间查询. 但是假设现在有: 1.区间修改,单点查询 2.区间修改,区间查询 但是又不想敲线段树怎么办? 就用树状数组喽. 假设现在有一个原数组a(假设a[0] = 0),有一个数组d,d[i] = a[i] - a[i-1],那么 a[i] = d[1] + d[2] + .... + d[i] d数组就是差分数组 所以求a[i]就可以用树状数组维护d[i]的前缀和 区间修改,单点查询: 根据d的定义,对[l,r]区间加上x,那么a[l]和a

差分数组的实现

差分数组的功能是修改区间,查询点 修改区间的时间复杂度是O(1),查询点的时间复杂度为O(n) 我们这里要根据数据范围灵活选取方法,不要拘泥于差分数组 void update(int x,int y,int z) { b[x]+=z; b[y+1]-=z; } 以上是修改区间操作,x位置加上修改量,y+1位置减去修改量,这样整个区间的元素就相当于修改了 int sum(int x) { int ans=0; for(int i=1;i<=x;i++) ans+=b[i]; return ans;

差分数组 and 树上差分

差分数组 定义 百度百科中的差分定义 //其实这完全和要讲的没关系 qwq 进去看了之后是不是觉得看不懂? 那我简单概括一下qwq 差分数组de定义:记录当前位置的数与上一位置的数的差值. 栗子 容易发现的是,\(\sum_{j=1}^{i} b_j\)即代表\(a_i\) 的值. \((\sum\) 即代表累加.) 思想 看到前面的\(\sum\) 你一定会发现这是前缀和! 那你认为这是前缀和? 的确是qwq. 实际上这并不是真正意义上的前缀和. 前缀和的思想是 根据元素与元素之间的并集关系(

Karen and Coffee CodeForces - 816B (差分数组+预处理前缀和)

To stay woke and attentive during classes, Karen needs some coffee! Karen, a coffee aficionado, wants to know the optimal temperature for brewing the perfect cup of coffee. Indeed, she has spent some time reading several recipe books, including the u

P1083 借教室 差分数组

第一行包含两个正整数n,mn,m,表示天数和订单的数量. 第二行包含nn个正整数,其中第ii个数为r_iri?,表示第ii天可用于租借的教室数量. 接下来有mm行,每行包含三个正整数d_j,s_j,t_jdj?,sj?,tj?,表示租借的数量,租借开始.结束分别在第几天. 每行相邻的两个数之间均用一个空格隔开.天数与订单均用从11开始的整数编号. 输出格式: 如果所有订单均可满足,则输出只有一行,包含一个整数00.否则(订单无法完全满足) 输出两行,第一行输出一个负整数-1−1,第二行输出需要修