題目描述:
給你一個整數 n 和一個下標從 0 開始的 二維數組 queries ,其中 queries[i] = [typei, indexi, vali] 。
一開始,給你一個下標從 0 開始的 n x n 矩陣,所有元素均為 0 。每一個查詢,你需要執行以下操作之一:
如果 typei == 0 ,將第 indexi 行的元素全部修改為 vali ,覆蓋任何之前的值。
如果 typei == 1 ,將第 indexi 列的元素全部修改為 vali ,覆蓋任何之前的值。
請你執行完所有查詢以后,返回矩陣中所有整數的和。
示例 1:
輸入:n = 3, queries = [[0,0,1],[1,2,2],[0,2,3],[1,0,4]]
輸出:23
解釋:上圖展示了每個查詢以后矩陣的值。所有操作執行完以后,矩陣元素之和為 23 。
示例 2:
輸入:n = 3, queries = [[0,0,4],[0,1,2],[1,0,1],[0,2,3],[1,2,1]]
輸出:17
解釋:上圖展示了每一個查詢操作之后的矩陣。所有操作執行完以后,矩陣元素之和為 17 。
解題思路:
這道題很巧妙,所以我決定把它分享出來。
這道題正常來講,讀完題第一反應就是直接暴力就能做,就改數唄,然后加和唄。
但是這有點太暴力了,那就優化一下,不改所有的數了,就改每一行的和和每一列的和唄,最后再統計一下總和。但這樣似乎好像也不是很好實現。因為我們把每一行和每一列的和記錄下來之后,最后算總和的時候是不太好計算的,因為后改變的會覆蓋先改變的,所以我們還得知道行和列改變的順序關系才行。
那考慮到這,注意到加粗的“順序關系”了么,沒錯,這就是解題關鍵。
后改變的會覆蓋先改變的,也就是說,我只需要從最后改變的開始往前遍歷就行了,最后改變的一定是貢獻給最終答案的,那先前改變的就沒有作用了。所以無論是行還是列,我們都只關注他是不是最后改變的,我們從后往前遍歷的話,也就是關注他是不是第一個出現的,如果是那就更新最終的答案的值,如果不是說明在這個操作后面有另一個操作把它覆蓋了,這個操作不起作用。
代碼:
class Solution {
public:long long matrixSumQueries(int n, vector<vector<int>>& queries) {long long int ans = 0;unordered_set<int> vis[2]; //0表示行是否被修改,1表示列是否被修改int m = queries.size();for(int i = m - 1 ; i >= 0 ; i--){auto &q = queries[i];int type = q[0] , index = q[1] , val = q[2];if(!vis[type].count(index)){//如果該行/列沒有被修改過ans += (long long int)(n-vis[type^1].size())*val;//更新答案,該行/列首次發生改變的數要加到最終答案里vis[type].insert(index);//標記該行/列已經被修改過}}return ans;}
};