uvalive4327(單調佇列優化)

2022-08-24 20:51:08 字數 1723 閱讀 4304

這題我有閃過是用單調佇列優化的想法,也想過有左右兩邊各燒一遍。 但是不敢確定,搜了題解,發現真的是用單調佇列,然後寫了好久,調了好久下標應該怎麼變化才過的。

dp[i][j] 表示走到第i行,第j個豎線的最大價值。

dp[i][j] = max(dp[i-1][k]+pre[i][j-1]-pre[i][k-1]);  從左往右

dp[i][j] = max(dp[i][j],dp[i-1][k]+suf[i][j]-suf[i][k]); 從右往左

1

#pragma warning(disable:4996)

2#pragma comment(linker, "/stack:1024000000,1024000000")

3 #include 4 #include

5 #include 6 #include 7 #include 8 #include

9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include

16 #include 17

const

int inf = 1

<< 30;18

typedef __int64 ll;

19/*

20dp[i][j]表示走到第i個橫線,第j個豎線的最大值

21dp[i][j] = max(dp[i-1][k] + sum[j-1] - sum[k-1])

22單調佇列優化維護隊首最大值,

23*/

2425

int q[11111

], head, tail;

26int dp[111][11111

];27

int a[111][11111

];28

int b[111][11111

];29

int pre[111][11111], suf[111][11111

];30

int sum1[111][11111

];31

int sum2[111][11111

];32

intmain()

3352

for (int j = m;j >= 1;--j)

53 suf[i][j] += suf[i][j + 1

];5455}

56for (int i = 1;i <= n;++i)

5764

for (int j = m;j >= 1;--j)

65 sum1[i][j] += sum1[i][j + 1

];66}67

for (int i = n;i >= 1;--i)

6879 head = tail = 0;80

81for (int j = m+1;j >= 1;--j)

8290}91

int ans = 0;92

for (int j = 1;j <= m + 1;++j)

93 ans = std::max(ans, dp[1

][j]);

94 printf("

%d\n

", ans);95}

96return0;

97 }

view code

單調棧,單調佇列

大多數借鑑了 單調佇列是什麼呢?可以直接從問題開始來展開。poj 2823 給定乙個數列,從左至右輸出每個長度為m的數列段內的最小數和最大數。數列長度 n 106,m n 我們知道,解法 在暴力列舉的過程中,有乙個地方是重複比較了,就是在找當前的f i 的時候,i的前面其它m 1個數在算f i 1 ...

單調棧 單調佇列

單調棧 單調佇列是在棧和佇列的基礎上加上單調結構的資料結構。如果乙個元素入棧或入隊,他會檢查之前的元素,如果之前的元素不可能是答案的解,那麼就彈出元素,使得當前元素入棧或入隊。leetcode 239 滑動視窗最大值 此題是單調佇列,每次遇到乙個元素,一直從隊尾彈出,直到隊尾元素大於該元素為止。還需...

單調棧 單調佇列

啊學完了來寫個總結吧 顧名思義,單調,就是指色彩單一某乙個容器裡面的元素都是遞增或遞減的,而單調棧和單調佇列就是這個容器。單調棧 單調棧模板 其他的我就不說了,講下為什麼單調棧是從後往前掃瞄 當我們在判斷乙個數後面第乙個比它大的數時,前提是後面的數已經被處理了,所以我們要從後往前掃瞄。我做了兩種做法...