1. 程式人生 > 實用技巧 >ACwing(基礎)--- 字首和、差分

ACwing(基礎)--- 字首和、差分

一維字首和

顧名思義:字首和就是陣列前n項和

注意:陣列下標從1開始防止越界

1、預處理字首和陣列
2、用公式求區間和

//求字首和
s[i] = s[i-1]+a[i];
//求陣列下標在l,r之間的元素之和
s[r]-s[l-1]

二維字首和

用二維矩陣來計算

// 求s[i,j] 表示矩陣大小為行i,列j的元素之和
s[i][j] = s[i-1][j]+s[i][j-1] - s[i-1][j-1] + a[i][j];
// 求s[x1,y1]到s[x2,y2]之間的元素之和
s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1];
#include<iostream>

using namespace std;
const int N = 1010;

int n,m,q;
int a[N][N],s[N][N];

int main(){
    cin >> n >> m >> q;
    for(int i = 1; i <= n; i ++ ){
        for(int j = 1; j <= m; j ++ ){
            cin>>a[i][j];
            s[i][j] = s[i-1][j]+s[i][j-1] - s[i-1][j-1] + a[i][j];
        }
    }
    
    while(q -- ){
        int x1,x2,y1,y2;
        cin>>x1>>y1>>x2>>y2;
        cout<<s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]<<endl;
    }
    return 0;
}

一維差分

給定a[1],a[2],...a[n]構造差分陣列b[N],使得a[i] = b[1]+b[2]+...+b[i]
b[i]=a[i]-a[i-1];
核心操作:將a[L~R]全部加上C,等價於:b[L]+=C,b[R+1] -= C;
1、a[1~L-1]無影響
2、a[L~R]加上了C
3、a[R+1~N]無影響

實現差分

有的操作利用了字首和,差分是字首和的逆運算

// b[N] 初始全為0
void insert(int l,int r,int c){
    b[l]+=c;
    b[r+1]-=c;
}
//利用字首和來還原陣列資料
for(int i = 1; i <= n; i ++ ) a[i] = a[i-1] + b[i];


//整體操作:計算差分陣列b[N],將序列中[l, r]之間的每個數加上c,還原原陣列
#include<iostream>

using namespace std;
const int N = 1e5+10;

int n,m;
int a[N],b[N];

void insert(int l,int r,int c){
    b[l]+=c;
    b[r+1]-=c;
}

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

二維差分

給定原矩陣a[i,j],構造差分矩陣b[i,j],使得a[][]是b[][]的二維字首和

二維差分核心操作

給以(x1,y1)為左上角,(x2,y2)為右下角的子矩陣中的所有數a[i,j],加上C。

//對於差分陣列的影響:

b[x1,y1] += C;
b[x1,y2+1] -=C;
b[x2+1,y1] -= C;
b[x2+1,y2+1] +=C;
#include<iostream>

using namespace std;
const int N = 1e3+10;

int n,m,q;
int a[N][N],b[N][N];

void insert(int x1,int y1,int x2,int y2,int c){
	b[x1][y1]+=c;
	b[x1][y2+1]-=c;
	b[x2+1][y1]-=c;
	b[x2+1][y2+1]+=c;
}
int main(){
	cin >> n >> m >> q;
	for(int i = 1; i <= n; i ++ ){
		for(int j = 1; j <= m; j ++ ){
			cin>>a[i][j];
		}
	}
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= m; j ++ ){
			insert(i,j,i,j,a[i][j]);
		}
	}
	
	while(q --){
		int x1,y1,x2,y2,c;
		cin>>x1>>y1>>x2>>y2>>c;
		insert(x1,y1,x2,y2,c);
	}
	
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= m; j ++ ){
			a[i][j] = a[i-1][j]+a[i][j-1]-a[i-1][j-1]+b[i][j];
		}
	}
	
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= m; j ++ ){
			cout<<a[i][j]<<" ";
		}
		puts("");
	}	
}