一、差分数组的定义及用途
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项的和,那么推导可知
即可用差分数组求出数列前缀和;
3.用途:
(1)快速处理区间加减操作:
假如现在对数列中区间[L,R]上的数加上x,我们通过性质(1)知道,第一个受影响的差分数组中的元素为f[L],即令f[L]+=x,那么后面数列元素在计算过程中都会加上x;最后一个受影响的差分数组中的元素为f[R],所以令f[R+1]-=x,即可保证不会影响到R以后数列元素的计算。这样我们不必对区间内每一个数进行处理,只需处理两个差分后的数即可;
(2)询问区间和问题:
由性质(2)我们可以计算出数列各项的前缀和数组sum各项的值;那么显然,区间[L,R]的和即为ans=sum[R]-sum[L-1];
总的来说差分数组适用于离线的区间修改问题,如果是在线的话应该用线段树或其他数据结构。
题目:点击打开链接
题意: 中文题,不解释。
分析:以前是用线段树做的,有点麻烦,现在用差分数组做一下。对于区间[L,R],D数组的修改再容易不过了对于[L,R]中的元素,它们加上同样的数,之间的差值不变,不必修改唯一需要修改的就是差分数组D[L]=A[L]-A[L-1]和D[R+1]=A[R+1]-A[R]因为A[L]改了A[L-1]没改,A[R+1]没改但A[R]改了,只有它们的差值改变了,所以对于区间[L,R]加上v的操作,我们只需令D[L]+=v,D[R+1]-=v,最后求一次前缀和就是新的A数组啦。
代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include<algorithm>
#include<iostream>
#include<fstream>
#include<complex>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iomanip>
#include<string>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cctype>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<map>
using namespace std;
#define pt(a) cout<<a<<endl
#define debug test
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
typedef pair<int,int> PII;
const ll mod = 1e9+7;
const int N = 1e6+10;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int n,a[N],d[N];
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
while(cin>>n&&n) {
mst(d,0),mst(a,0);
rep(i,1,n) {
int x,y;
cin>>x>>y;
d[x]++,d[y+1]--;
}
rep(i,1,n) a[i]=a[i-1]+d[i];
rep(i,1,n-1) cout<<a[i]<<" ";
cout<<a[n]<<endl;
}
return 0;
}