前缀和&差分

一、一维前缀和(求区间L~R的区间和或者乘积)

此处例题icon-default.png?t=M5H6http://acm.mangata.ltd/p/P1501

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mod 1e9+7
const int N=2e5+9;
ll a[N],pre[N],ans=1;

int main(){
	ll n,m;
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		cin>>a[i];
		pre[i]=pre[i-1]+a[i];
	}
	while(m--){
		ll p,q;
		cin>>p>>q;
		ans=pre[q]-pre[p-1];
		cout<<ans<<"\n";
	}
	
	
	return 0;
}

二、二维前缀和

例题icon-default.png?t=M5H6https://www.luogu.com.cn/problem/P2004

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mod 10000
const int N=2001;
ll a[N][N];
ll pre[N][N];

int main(){
	ll n,m,c,max=-2e6+15,x,y;
	cin>>n>>m>>c;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			cin>>a[i][j];
			pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+a[i][j];
		}
	}
	for(int i=c;i<=n;++i){
		for(int j=c;j<=m;++j){
			if(pre[i][j]-pre[i-c][j]-pre[i][j-c]+pre[i-c][j-c]>max){
				max=pre[i][j]-pre[i-c][j]-pre[i][j-c]+pre[i-c][j-c];
				x=i-c+1;
				y=j-c+1;
			}
		}
	}
	cout<<x<<" "<<y;
	return 0;
} 

三、差分(差分可以看成前缀和的逆运算

区别:

差分数组:

首先给定一个原数组a:a[1], a[2], a[3],,,,,, a[n];

然后我们构造一个数组b : b[1] ,b[2] , b[3],,,,,, b[i];

使得 a[i] = b[1] + b[2 ]+ b[3] +,,,,,, + b[i]

也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数组。换句话说,每一个a[i]都是b数组中从头开始的一段区间和。

例题:

输入一个长度为 n 的整数序列。

接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。

请你输出进行完所有操作后的序列。

输入格式
第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数序列。

接下来 m 行,每行包含三个整数 l,r,c,表示一个操作。

输出格式
共一行,包含 n 个整数,表示最终序列。

数据范围
1≤n,m≤100000,
1≤l≤r≤n,
−1000≤c≤1000,
−1000≤整数序列中元素的值≤1000
输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mod 1e9+7
const int N=2001;
ll a[N],b[N];

int main(){
	ll n,m;
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		cin>>a[i];
		b[i]=a[i]-a[i-1];
	}
	ll l,r,c;
	while(m--){
		cin>>l>>r>>c;
		b[l]+=c;
		b[r+1]-=c;
	}
	
	for(int i=1;i<=n;++i){
		a[i]=b[i]+a[i-1];
		cout<<a[i]<<" ";
	}
	
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值