Monotonic stack:
POJ3250
There are n cows in a row. Look to the right. Each cow can only see the shorter cows. That is, it will be blocked by the higher cows. Ask how many cows can be seen.
Idea: consider the number of times each cow can be seen by the front cow, that is, the length of the monotonically decreasing sequence starting from the left side of the cow. Use monotone stack to maintain it.
Code:
#include<cstdio> #include<stack> using namespace std; const int maxn = 80005; stack<int > s; int main() { int n,x; long long sum = 0; scanf("%d",&n); scanf("%d",&x); s.push(x); for(int i = 1;i < n;i++) { scanf("%d",&x); while(!s.empty() && s.top() <= x) s.pop(); sum += s.size(); s.push(x); } printf("%lld\n",sum); return 0; }
Monotone queue:
Poj2823
Meaning: give a sequence of length n and interval length k, and ask the maximum and minimum values of each interval of length k from left to right.
Idea: for the minimum value, consider maintaining an increasing two terminal queue, delete all the elements of the end to end ratio of the current queue each time when entering the queue, take the head of the queue each time and judge whether it is within the current range.
Code:
#include<cstdio> #include<deque> #include<iostream> #include<algorithm> #include<utility> using namespace std; const int maxn = 1e6+5; deque<int> Q1,Q2; int a[maxn]; int n,k; void solve1() { for(int i = 1;i <= n;i++) { while(!Q1.empty() && a[Q1.back()] >= a[i]) Q1.pop_back(); Q1.push_back(i); if(i>=k) { while(!Q1.empty() && Q1.front() < i-k+1) Q1.pop_front(); printf("%d ",a[Q1.front()]); } } } void solve2() { for(int i = 1;i <= n;i++) { while(!Q2.empty() && a[Q2.back()] <= a[i]) Q2.pop_back(); Q2.push_back(i); if(i>=k) { while(!Q2.empty() && Q2.front() < i-k+1) Q2.pop_front(); printf("%d ",a[Q2.front()]); } } } int main() { scanf("%d%d",&n,&k); for(int i = 1;i <= n;i++) scanf("%d",&a[i]); solve1(); printf("\n"); solve2(); return 0; }