單調棧的性質及應用
阿新 • • 發佈:2019-01-26
ZZULI XXX
題意:給你一串序列,要你求所有子序列的最小值之和。(n很大,無法暴力)
思路:完美的單調棧模板
這裡簡要介紹下單調棧的性質,(其他的都沒用)
單調棧的維護是 O(n) 級的時間複雜度,因為所有元素只會進入棧一次,並且出棧後再也不會進棧了。
單調棧的性質:
1.單調棧裡的元素具有單調性
2.元素加入棧前,會在棧頂端把破壞棧單調性的元素都刪除
3.使用單調棧可以找到元素向左遍歷第一個比他小的元素,也可以找到元素向左遍歷第一個比他大的元素。
(也就是說在元素進棧前他向左拓展的區間已經確定,在出棧前她能向右拓展的區間也能確定)
程式碼如下:
#include<map> #include<stack> #include<queue> #include<vector> #include<string> #include<math.h> #include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<algorithm> #include<functional> using namespace std; typedef long long ll; #define inf 1000000000 #define mod 1000000007 #define maxn 286000 #define PI 3.1415926 #define lowbit(x) (x&-x) #define eps 1e-9 struct node { long long x, y, l, r; }str[maxn]; stack<node>t; int main() { long long T, i, j, n, m, k, sum; scanf("%lld", &T); while (T--) { sum = 0; scanf("%lld", &n); for (i = 1;i <= n;i++) { scanf("%lld", &str[i].x); str[i].y = i; } for (i = 1;i <= n;i++) { str[i].l = i; while (t.empty() == 0 && t.top().x>str[i].x) { str[t.top().y].r = i - 1; str[i].l = str[t.top().y].l; t.pop(); } t.push(str[i]); } while (t.empty() == 0) { str[t.top().y].r = n; t.pop(); } for (i = 1;i <= n;i++) sum += str[i].x*(i - str[i].l + 1)*(str[i].r - i + 1); printf("%lld\n", sum); } }