ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

基础算法----前缀和 and 差分

2021-11-04 20:34:26  阅读:157  来源: 互联网

标签:前缀 ll 差分 ---- nsum 数组 psum


前缀和

f[i] [j]为前缀和数组,a[i] [j]为原数组

f[i] [j] = f[i-1] [j] + f[i] [j-1] - f[i-1] [j-1] + a[i] [j]

算区间前缀和,画个图推公式

差分

原数组a[i], 差分数组f[i] = f[i] - f[i-1], f[1] = a[1]

性质1:差分数组的前缀和序列为a, 即差分数组前缀和s[i], s[i] = a[i];

性质2:给原数组a区间在[l, r]各加d ,f[l] += d, f[r+1] -= d(减d则是f[l] -= d, f[r+1] += d), f其余不变---->当对原数组进行区间操作时,可以转化成对差分数组的单店操作

例:

给定一个长度为 n 的数列 a1,a2,…,an每次可以选择一个区间 [l,r],使下标在这个区间内的数都加一或者都减一。

求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。

输入格式

第一行输入正整数 n。

接下来 n 行,每行输入一个整数,第 i+1行的整数代表 ai。

输出格式

第一行输出最少操作次数。

第二行输出最终能得到多少种结果。

数据范围

0<n≤105
0≤ai<2147483648

输入样例:

4
1
1
2
2

输出样例:

1
2

已知差分数组性质2,每次可以令差分数组中的一个数+1,另一个数-1,目的是将差分数组b[2] - b[n]都变为0

先求出差分数组b,令psum为b中的正数和,nsum为b中的负数和的绝对值,之后可以先进行min(psum, nsum)次,进行相平,之后还差|psum - nsum|下相平,可以再把这些数字和b1或b[n-1]进行相平(b[1]与b[n+1]的值不影响结果),因此总操作次数为min(psum, nsum) + |psum - nsum|, 而总结果种类可以为0到|psum - nsum|任意一种,因此总结果种数为|psum - nsum| + 1

代码示例:

ll a[100005];
ll b[100005];
ll n, nsum, psum;
ll ans;
ll cnt;

int main ()
{	
	cin >> n;
	For(i, 1, n) cin >> a[i];
	b[1] = a[1];
	For(i, 2, n) 
	{
		b[i] = a[i] - a[i-1];
		if(b[i] < 0) nsum += b[i];
		else psum += b[i];
	}
	nsum *= -1;

	ll tm = psum - nsum;
	if(tm < 0) tm *= -1;
	ans += min(psum, nsum);
	ans += tm;
   
	cnt = tm + 1;
	cout << ans << endl << cnt << endl;
	return 0;
}	

标签:前缀,ll,差分,----,nsum,数组,psum
来源: https://www.cnblogs.com/yramvj/p/15510236.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有