差分与前缀和
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了差分与前缀和相关的知识,希望对你有一定的参考价值。
前置知识
前缀和
一维前缀和:
s [ i ] = a [ 1 ] + a [ 2 ] + . . . + a [ i ] s[i]=a[1]+a[2]+...+a[i] s[i]=a[1]+a[2]+...+a[i]
初始化:
for(int i=1;i<=n;i++)
s[i] = s[i-1] + a[i];
二维前缀和:
s
[
i
]
[
j
]
s[i][j]
s[i][j] : 第i
行第j
列左上部分所有元素的和
以 ( x 1 , y 1 ) (x_1, y_1) (x1,y1)为左上角, ( x 2 , y 2 ) (x_2, y_2) (x2,y2)为右下角的子矩阵的和为:
矩阵长宽都为1
s
[
x
2
]
[
y
2
]
−
s
[
x
2
−
1
]
[
y
2
]
−
s
[
x
2
]
[
y
2
−
1
]
+
s
[
x
2
−
1
]
[
y
2
−
1
]
s[x2][y2] - s[x2 - 1][ y2] - s[x2][ y2 - 1] + s[x2 - 1][ y2 - 1]
s[x2][y2]−s[x2−1][y2]−s[x2][y2−1]+s[x2−1][y2−1]
矩阵长宽都为k
s
[
x
2
]
[
y
2
]
−
s
[
x
2
−
k
]
[
y
2
]
−
s
[
x
2
]
[
y
2
−
k
]
+
s
[
x
2
−
k
]
[
y
2
−
k
]
s[x2][y2] - s[x2 - k][ y2] - s[x2][ y2 - k] + s[x2 - k][ y2 - k]
s[x2][y2]−s[x2−k][y2]−s[x2][y2−k]+s[x2−k][y2−k]
差分
差分数组b[i]
代表a[i]-a[i-1]
两个元素之间的差
给区间
[
l
,
r
]
[l, r]
[l,r]中的每个数加上c
:
b
[
l
]
+
=
c
,
b
[
r
+
1
]
−
=
c
b[l] += c, b[r + 1] -= c
b[l]+=c,b[r+1]−=c
两者结合
差分数组b[i]=a[i]-a[i-1]
差分前缀和数组s[i]=s[i-1]+b[i]
做区间修改时一直进行差分数组的操作,最后统计时利用差分数组计算差分前缀和。
注意是差分前缀和,是最后一个值与前面初始值之间(初始值如果用的是0,则表示当前值)的差距,而不是真正的前缀和。
s
[
i
]
=
s
[
i
−
1
]
+
b
[
i
]
s[i] = s[i-1] + b[i]
s[i]=s[i−1]+b[i]
s
[
i
]
s[i]
s[i]为区间修改之后的a[i]
题目
蓝彗星
链接:
https://ac.nowcoder.com/acm/contest/23479/C
s1[i]
:代表B的差分
s2[i]
:代表R的差分
对差分求前缀和得到的是当前值,如果当前值为正说明存在,为0说明不存在
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int main()
vector<int>s1(N,0),s2(N,0);
int n,t;
cin>>n>>t;
string s;
cin>>s;
for(int i=1;i<=n;i++)
int x;cin>>x;
if(s[i-1]=='B') s1[x]++, s1[x+t]--;
else s2[x]++, s2[x+t]--;
int res = 0;
for(int i=1;i<=2e5;i++)
s1[i] += s1[i-1];
s2[i] += s2[i-1];
res += (s1[i] && !s2[i]);
cout<<res<<endl;
return 0;
把它当成思维题来写:
bl,br
为B的左右区间
R只负责对B的区间进行切割
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int N = 1e5+5;
pair<int,char>p[N];
int main()
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>p[i].se;
for(int i=1;i<=n;i++) cin>>p[i].fi;
sort(p+1,p+1+n);
ll res = 0;
int bl = 0,br = 0;
int rl=0,rr=0;
for(int i=1;i<=n;i++)
if(p[i].se == 'B') //yanxu jisuan
if(p[i].fi>br)
res += max(br-bl,0);
bl = max(rr,p[i].fi);
br = p[i].fi + k;
else br = max(p[i].fi + k,br);
if(p[i].se == 'R')//qiege
br = min(p[i].fi,br);
rr = max(rr,p[i].fi + k);
// cout<<bl<<"--"<<br<<endl;
if(bl and br) res += max(br-bl,0);
cout<<res<<endl;
return 0;
以上是关于差分与前缀和的主要内容,如果未能解决你的问题,请参考以下文章