栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

前缀和差分

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

前缀和差分

目录

第一题:100. 增减序列 - AcWing题库

第二题:​​​​​​101. 最高的牛 - AcWing题库


今天主要说一说差分吧,之前一直知道差分但感觉好像没什么用,但其实挺好用,如果可以的话,能大大降低复杂度,主要就是把区间的统一操作变化到区间端点上,假如把一个区间同时加上或者减去d,只需要把原序列的差分数组求出来c[l]+=d,c[r+1]-=d,很妙。原序列的差分数组和差分数组的前缀和是等价的,设原数组是a,差分数组是b,那b[i]=a[i]-a[i-1],这个式子有个隐含的条件就是a[1]==b[1],然后开始进行差分,通俗的来说差分数组就是后一个数-前一个数,然后第一个数字相同,就这个,下面来看看题:

第一题:100. 增减序列 - AcWing题库

题意就是给你一个序列,然后选择任意的区间进行+1或者-1,最终得到这个序列完全一样,问最少操作多少次,还有问这样的序列能有多少种?(数据范围1e5)

题解:任意区间操作,数据范围那么大,暴力肯定不行,很容易能想到差分,我想了想差分好像没有头绪,感觉乱糟糟的。后来看题解才明白要分情况讨论:

刚刚有一点很重要,就是原数组和差分数组的第一个数是相同的,就借助这个性质来分类,还有差分数组的前缀和是原数组,所以希望b2,b3...bn都是0,然后原序列就是n个b1,这是最优解

分类讨论:(这里设p为正数的和,q为负数绝对值的和)

①2<=i,j<=n-1 那这里的操作次数就是min(p,q),//这里的点要注意,可以选择任意区间,我刚开始想的是正数的个数和负数的个数,其实要看总和,任意区间都可以选,最好的情况是正数的和==负数的绝对值的和,那在第一种情况就可以得到相等的数组

②(前缀)i==1,2<=j<=n-1,这里就是直接|p-q|,第一个情况剩下来的,要从第一个数进行改变了

③(后缀),同理2

④全部(无意义)

所以综上所述,最少的操作次数等于min(p,q)+|p-q|==max(p,q)

不同的种类数:|p-q|+1

代码:

#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N],b[N];
int main(){
	ll n;
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++) b[i]=a[i]-a[i-1];
	ll p=0,q=0;
	for(int i=2;i<=n;i++)
	{
		if(b[i]>0) p+=b[i];
		else if(b[i]<0) q-=b[i];
	}
	cout< 

第二题:​​​​​​101. 最高的牛 - AcWing题库

题意就是给你一个n头牛中最高的牛的编号和高度和m对关系,这两头牛能相互看见,中间的牛必须不高于这两头牛,求每头牛最高可能是多高

这个题我想了一下,思路和题解是一样的,就是最高的牛和能看见最远的地方肯定都是h,往里面-1,但是不太会写出来,但其实很简单啦

设c数组是改变数组,就是在每头牛的基础上改变了多少,设d为c数组的差分数组

c的初始都是0,(当然最高的那头肯定一直都是0),就刚刚的思路,两个区间l,r,c[l+1]--,c[r-1]--自己手动模拟一下(我就不配图了QAQ),因为c是一段区间上的操作,所以d只需要在两个端点上操作就好(这里要注意,可能会有重复关系,还需要判断一下,还有给的关系的区间并不是l

#include
#include
using namespace std;
typedef pair PAII;
map mp;
const int N=1e6+10;
int c[N],d[N],H[N];//c是改变数组,d是c的差分数组 
int main(){
	int n,p,h,m;
	cin>>n>>p>>h>>m;
	for(int i=1;i<=m;i++)
	{
		int l,r;
		cin>>l>>r;
		if(l>r) swap(l,r);
		if(mp[{l,r}]) continue;
		mp[{l,r}]=true;
		d[l+1]--;
		d[r]++;
	}
	for(int i=1;i<=n;i++) c[i]=c[i-1]+d[i];
	//for(int i=1;i<=n;i++) cout< 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/971182.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号