1215 陣列的寬度
基準時間限制:1 秒 空間限制:131072 kb 分值: 80
收藏關注n個整數組成的陣列,定義子陣列a[i]..a[j]的寬度為:max(a[i]..a[j]) - min(a[i]..a[j]),求所有子陣列的寬度和。
input
第1行:1個數n,表示陣列的長度。(1 <= n <= 50000)output第2 - n + 1行:每行1個數,表示陣列中的元素(1 <= a[i] <= 50000)
輸出所有子陣列的寬度和。input示例
512345output示例
20以1 5 4 2 3為例,逐個入棧計算每個數的右邊界:思路:單調棧;
我們只要統計每個數做為最小的數和最大的數所在區間有多少個。這樣求當前數作為最大的數左右範圍,這個用單調棧維護下,同理最小的也是
然後左區間大小乘右區間大小就是這個數作為最大的出現的區間數;
1入棧 => 1
5入棧,前面所有比5小的出棧,並將右邊界設為5 => 5 (確定了1的右邊界是5,對應下標為1)
4入棧,前面所有比4小的出棧,並將右邊界設為4 => 5 4
2入棧,前面所有比2小的出棧,並將右邊界設為2 => 5 4 2
3入棧,前面所有比3小的出棧,並將右邊界設為3 => 5 4 3(確定了2的右邊界是3,對應下標為4)
最後所有數出棧,將5 4 3這3個數的右邊界的下標設為5。
這樣可以確認,每個數字最多進一次棧出一次棧,所有複雜度是o(n)的。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include
8 #include9
using
namespace
std;
10 typedef long
long
ll;11 typedef struct
node
12 ss;
16 ll ans[60000
];17
int ll[60000
];18
int rr[60000
];19 stackstcx;
20int main(void)21
31while(!stcx.empty())
32stcx.pop();
33for(i = 1; i <= n; i++)
3447
else
4852}53
if(stcx.empty())
5461}62
while(!stcx.empty())
6369
70for(i = 1; i <= n; i++)
7174
for(i = 1; i <= n; i++)
7588
else
8993}94
if(stcx.empty())
95102
}103
while(!stcx.empty())
104109
for(i = 1; i <= n; i++)
110113 printf("
%lld\n
",sum);
114}
115return0;
116 }
51Nod 1215 陣列的寬度
acm模版 在討論區中,夾克老師講得十分透徹了,我也不再做那麼詳細贅述了,大致的分析一下,根據夾克老師的說法,用單調棧分別求出來乙個數作為最大值和最小值的貢獻區間,也就是說求出這個數作為最大或者最小的值時能往前往後延伸的長度,最後根據乘法原則就能求出來每個數貢獻的區間數目。先單調遞減棧搞一遍,求出每...
51Nod1215 陣列的寬度
題目看這裡 各種求和最好玩的啦 看到題目就應該知道要單獨考慮每個元素的貢獻 那麼乙個元素i的貢獻肯定是a i l i i i r i 這裡l,r分別表示左邊和右邊第乙個比i大的數的位置 最大值部分的貢獻算完了最小值是類似的 考慮怎麼求這個l和r,直接上單調棧就可以了 code很難看當時不知道在想什麼...
51Nod 1215 陣列的寬度(單調棧)
題目描述 思路 單調棧處理左右第一處比自己小和大的位置,然後計算每個元素對答案的貢獻,注意若干相同元素不能重複計算,所以在處理左邊第一處大於自己的位置後,右邊就要處理第一處大於等於自己的位置,這樣才不會重複計算,比自己小的位置也同理 include include include include i...