1、字首和
輸入乙個長度為n的整數序列。
接下來再輸入m個詢問,每個詢問輸入一對l, r。
對於每個詢問,輸出原序列中從第l個數到第r個數的和。
輸入格式
第一行包含兩個整數n和m。
第二行包含n個整數,表示整數數列。
接下來m行,每行包含兩個整數l和r,表示乙個詢問的區間範圍。
輸出格式
共m行,每行輸出乙個詢問的結果。
資料範圍
1≤l≤r≤n1≤l≤r≤n,
1≤n,m≤1000001≤n,m≤100000,
−1000≤數列中元素的值≤1000−1000≤數列中元素的值≤1000
輸入樣例:
5 3
2 1 3 6 4
1 21 3
2 4
輸出樣例:
3
610
//步驟: 定義s存每個位置的字首和s[i] = s[i - 1] + a[i],l-r區間和:s[r] - s[l - 1]
#include using namespace std;
const int n = 100010;
int a[n], s[n];//少了這個s[n]: si = a1 + a2 + ...+ ai,
int main()
}
2、子矩陣和
輸入乙個n行m列的整數矩陣,再輸入q個詢問,每個詢問包含四個整數x1, y1, x2, y2,表示乙個子矩陣的左上角座標和右下角座標。
對於每個詢問輸出子矩陣中所有數的和。
輸入格式
第一行包含三個整數n,m,q。
接下來n行,每行包含m個整數,表示整數矩陣。
接下來q行,每行包含四個整數x1, y1, x2, y2,表示一組詢問。
輸出格式
共q行,每行輸出乙個詢問的結果。
資料範圍
1≤n,m≤10001≤n,m≤1000,
1≤q≤2000001≤q≤200000,
1≤x1≤x2≤n1≤x1≤x2≤n,
1≤y1≤y2≤m1≤y1≤y2≤m,
−1000≤矩陣內元素的值≤1000−1000≤矩陣內元素的值≤1000
輸入樣例:
3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4
輸出樣例:
17
2721
//步驟:初始化字首和:按照公式來:s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
//求輸出子矩陣中所有數的和:s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]
#include using namespace std;
const int n = 1010;
int a[n][n], s[n][n];
int main()
return 0;
}
3、差分
輸入乙個長度為n的整數序列。
接下來輸入m個操作,每個操作包含三個整數l, r, c,表示將序列中[l, r]之間的每個數加上c。
請你輸出進行完所有操作後的序列。
輸入格式
第一行包含兩個整數n和m。
第二行包含n個整數,表示整數序列。
接下來m行,每行包含三個整數l,r,c,表示乙個操作。
輸出格式
共一行,包含n個整數,表示最終序列。
資料範圍
1≤n,m≤1000001≤n,m≤100000,
1≤l≤r≤n1≤l≤r≤n,
−1000≤c≤1000−1000≤c≤1000,
−1000≤整數序列中元素的值≤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
//步驟:還是不熟練,晚上繼續寫一遍
//所有陣列進行插入操作:b[l] += c;b[r + 1] -= c;insert(i, i, a[i]),插入乙個數c,求原來陣列字首和:b[i] += b[i - 1];,輸出b[i]
/*概念助於理解
假設給定原陣列是 a1, a2, a3,..., an.
構造b陣列 b1,b2,...,bn.使得 ai = b1 + b2 + ... + bi;
則有 b1 = a1;
b2 = a2 - a1;
b3 = a3 - a2;
...an = an - an-1;
b則稱為a的差分,a則是b的字首和。字首和和差分是逆運算。
在a陣列裡面[l,r]區間加上乙個固定值c,即 al + c , al+1 + c ,...,ar + c;
對a陣列[l,r]區間加上c,又因為ai = b陣列得字首和,所以對b差分陣列來說同樣的也要加上c-->bl + c-->al
也會自動加上c-->al ... an都會加上c。但是加c只要執行到r,所以第r+1就要減去c,這樣就可以抵消r之後加上的c。
*/#include using namespace std;
const int n = 100010;
int a[n], b[n];
void insert(int l, int r, int c)
int main()
//求原來陣列的值,對差分陣列求字首和
for (int i = 1; i <= n; i ++) b[i] += b[i - 1];// 這裡是b[i] += b[i - 1];不是b[i] = b[i - 1]+ a[i];
for (int i = 1; i <= n; i ++) cout << b[i] << ' ';
return 0;
}
4、差分矩陣
輸入乙個n行m列的整數矩陣,再輸入q個操作,每個操作包含五個整數x1, y1, x2, y2, c,其中(x1, y1)和(x2, y2)表示乙個子矩陣的左上角座標和右下角座標。
每個操作都要將選中的子矩陣中的每個元素的值加上c。
請你將進行完所有操作後的矩陣輸出。
輸入格式
第一行包含整數n,m,q。
接下來n行,每行包含m個整數,表示整數矩陣。
接下來q行,每行包含5個整數x1, y1, x2, y2, c,表示乙個操作。
輸出格式
共 n 行,每行 m 個整數,表示所有操作進行完畢後的最終矩陣。
資料範圍
1≤n,m≤10001≤n,m≤1000,
1≤q≤1000001≤q≤100000,
1≤x1≤x2≤n1≤x1≤x2≤n,
1≤y1≤y2≤m1≤y1≤y2≤m,
−1000≤c≤1000−1000≤c≤1000,
−1000≤矩陣內元素的值≤1000−1000≤矩陣內元素的值≤1000
輸入樣例:
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
輸出樣例:
2 3 4 1
4 3 4 1
2 2 2 2
//步驟跟差分一樣的,不過多了一維,然後insert變了
/*1、insert:當bx1 y1加上c的時候,由於b是a的字首和,則會將點(x1, y1)左和下的元素加上c。所以我們要減去出去劃線之外的多餘的區域,所以需要減去 b(x2+1, y1) 和 b(x1, y2+1)。上圖所示但是減去兩者將會減兩次b(x2+1, y1) 和 b(x1, y2+1)重疊的區域,所以要將b(x2 +1,y2 + 1) 加回來.得到公式如下:
b(x1, y1) += c;
b(x2 + 1, y1) -= c;
b(x1, y2 + 1) -= c;
b(x2 + 1, y2 + 1) += c;
2、 求原來陣列的值,對差分陣列求字首和:b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
*/#include using namespace std;
const int n = 1010;
int n, m, q;
int a[n][n], b[n][n];
void insert(int x1, int y1, int x2, int y2, int c)
int main()
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];求原來陣列的值,對差分陣列求字首和
for (int i = 1; i <= n; i ++)
return 0;
}
牛客 每日一題 Xorto 題解(異或 字首和)
選取任意不重疊的兩個區間,使異或結果為0 前言已經想到了用字首和優化就是不知道該怎麼判斷他們不是重疊 正文暴力是列舉兩個區間左右端點,但是顯而易見會tle,我們可以考慮只列舉其中乙個區間 x,y 這個區間的異或和可以很容易的在o 1 時間複雜度通過字首異或和求得。如果我們規定 x,y 是右邊的那個區...
每日一題之 面試題 幸運巧克力(字首和 hash)
題目描述 思路 注意到每個元素都是 x 0,所以該陣列的字首和是遞增的。要找到連續的子串行之和等於k 即找到 sum i sum j k 且 0 j i 兩重for迴圈會超時,注意到字首和是遞增的,那麼將上式改寫成 sum i k sum j 這時候只要將字首和對映成下標,這樣只需要一重for迴圈,...
寒假刷題打卡第十九天 陣列和矩陣
錯誤的集合 最開始的想法是排序。但是 class solution int lose 1 int repeat 1 for int i 0 isize i return 尋找重複數 思路一 異或運算。先從1異或到n,將得到的值與陣列中的每個值異或運算。結果不對,因為,陣列中並非每個數都會出現一遍。思...