【差分与前缀和】

114 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前置知识

前缀和

一维前缀和: 一维前缀和:

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] : 第i行第j列左上部分所有元素的和

(x1,y1)(x_1, y_1)为左上角,(x2,y2)(x_2, y_2)为右下角的子矩阵的和为:

矩阵长宽都为1 s[x2][y2]s[x21][y2]s[x2][y21]+s[x21][y21]s[x2][y2] - s[x2 - 1][ y2] - s[x2][ y2 - 1] + s[x2 - 1][ y2 - 1]

矩阵长宽都为k s[x2][y2]s[x2k][y2]s[x2][y2k]+s[x2k][y2k]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]中的每个数加上cb[l]+=c,b[r+1]=cb[l] += c, b[r + 1] -= c

两者结合

差分数组b[i]=a[i]-a[i-1] 差分前缀和数组s[i]=s[i-1]+b[i] 做区间修改时一直进行差分数组的操作,最后统计时利用差分数组计算差分前缀和。 注意是差分前缀和,是最后一个值与前面初始值之间(初始值如果用的是0,则表示当前值)的差距,而不是真正的前缀和。 s[i]=s[i1]+b[i]s[i] = s[i-1] + b[i] s[i]s[i]为区间修改之后的a[i]


题目

蓝彗星

链接:
ac.nowcoder.com/acm/contest…


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;
}