這題我有閃過是用單調佇列優化的想法,也想過有左右兩邊各燒一遍。 但是不敢確定,搜了題解,發現真的是用單調佇列,然後寫了好久,調了好久下標應該怎麼變化才過的。
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]); 從右往左
1view code#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 }
單調棧,單調佇列
大多數借鑑了 單調佇列是什麼呢?可以直接從問題開始來展開。poj 2823 給定乙個數列,從左至右輸出每個長度為m的數列段內的最小數和最大數。數列長度 n 106,m n 我們知道,解法 在暴力列舉的過程中,有乙個地方是重複比較了,就是在找當前的f i 的時候,i的前面其它m 1個數在算f i 1 ...
單調棧 單調佇列
單調棧 單調佇列是在棧和佇列的基礎上加上單調結構的資料結構。如果乙個元素入棧或入隊,他會檢查之前的元素,如果之前的元素不可能是答案的解,那麼就彈出元素,使得當前元素入棧或入隊。leetcode 239 滑動視窗最大值 此題是單調佇列,每次遇到乙個元素,一直從隊尾彈出,直到隊尾元素大於該元素為止。還需...
單調棧 單調佇列
啊學完了來寫個總結吧 顧名思義,單調,就是指色彩單一某乙個容器裡面的元素都是遞增或遞減的,而單調棧和單調佇列就是這個容器。單調棧 單調棧模板 其他的我就不說了,講下為什麼單調棧是從後往前掃瞄 當我們在判斷乙個數後面第乙個比它大的數時,前提是後面的數已經被處理了,所以我們要從後往前掃瞄。我做了兩種做法...