題目連結:
題目大意:
輸入第一列給定一正整數 N(1 ≦ N ≦ 10 ^ 6),代表有 N 個同學排成一列。接著一列給定 N 個正整數(皆介於 1 ~ 10 ^ 9),代表每位同學的身高。
每位同學各自將會往左以及往右鄙視所有身高比他身高矮的同學,直到碰到不矮於他的身高之同學為止。
請輸出每位同學鄙視的同學們之身高總和。
範例輸入:
5
140 150 170 180 160
範例輸出:
0
140
290
620
0
解題思維:
先討論每個同學只「往左」鄙視到不矮於他的同學之情況:
我們可以維護一個堆疊 S(Stack),其從底部到堆疊頂端的元素保持著遞減之狀態,但是裡面的數字要大越好。而每個元素儲存著同學的編號(這邊定為從左至右編號為 1 ~ N),以及該位同學之身高這兩個資訊。
最一開始,我們將 (0, 2000000000) 這個資訊放到 S 的頂端,作為「界線」(因為不會有人身高值比 2000000000 大)。
接著從左至右掃過每位同學的身高 H。我們先判斷堆疊頂端的元素之身高是否 < H。如果是,則代表本同學的鄙視同學區間可以從 (此同學編號 - 堆疊頂端的同學編號) 繼續往左延伸,因此我們將 S 頂端移除掉(因為這個同學不再扮演任何重要的判斷用之角色)。重複此步驟直到堆疊頂端之身高 ≧ H。
此時我們便無法再繼續鄙視下去,因此此位同學將會鄙視所求為此同學(不含) ~ 堆疊頂端的同學(不含)之間所有的同學。而我們可以根據前綴和(Prefix Sums)之概念求出這個區間中的同學之身高總和(參見
這題)。最後我們將這位同學的編號以及身高放到 S 中,並繼續到下一個學生(如果有的話)。
而「往右」鄙視也是與上同理。從左至右和由右到左各掃一次後,便可以求出每位同學鄙視之同學身高總和。不過因為身高值可以到 10 ^ 9,所以對 C++ 等等語言需要宣告成長整數型態來儲存總和以免加總時溢位。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。