https://www.luogu.org/problem/P2947
题目描述
Each cow is looking to her left toward those with higher index numbers. We say that cow i 'looks up' to cow j if i < j and Hi < Hj. For each cow i, FJ would like to know the index of the first cow in line looked up to by cow i.
Note: about 50% of the test data will have N <= 1,000.
输入描述:
* Line 1: A single integer: N
* Lines 2..N+1: Line i+1 contains the single integer: Hi
输出描述:
* Lines 1..N: Line i contains a single integer representing the smallest index of a cow up to which cow i looks. If no such cow exists, print 0.
示例1
输入
6 3 2 6 1 1 2
输出
3 3 0 6 6 0
说明
FJ has six cows of heights 3, 2, 6, 1, 1, and 2.
Cows 1 and 2 both look up to cow 3; cows 4 and 5 both look up to cow 6; and cows 3 and 6 do not look up to any cow.
找每个数右边第一个大于等于它的位置,并输出该位置,如果没有就输出0
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <queue> 9 #include <set> 10 #include <map> 11 #include <math.h> 12 const int INF=0x3f3f3f3f; 13 typedef long long LL; 14 const int mod=1e9+7; 15 const int maxn=1e5+10; 16 using namespace std; 17 18 int A[maxn]; 19 int ans[maxn]; 20 21 int main() 22 { 23 int n; 24 scanf("%d",&n); 25 for (int i=1;i<=n;i++) 26 scanf("%d",&A[i]); 27 vector<int> vt; 28 vt.push_back(1); 29 int MIN=A[1]; 30 for (int i = 2; i <= n; i++) 31 { 32 if(A[i]>=MIN) 33 { 34 while (!vt.empty()) 35 { 36 if (A[*(vt.end()-1)]<A[i]) 37 { 38 ans[*(vt.end()-1)]=i; 39 vt.erase(vt.end()-1); 40 } 41 else 42 break; 43 } 44 vt.push_back(i); 45 } 46 else 47 { 48 vt.push_back(i); 49 MIN=ans[i]; 50 } 51 } 52 for (vector<int>::iterator it=vt.begin();it!=vt.end();it++) 53 { 54 ans[*it]=0; 55 } 56 for (int i=1;i<=n;i++) 57 printf("%d ",ans[i]); 58 return 0; 59 }
其实上面的代码就用到了单调栈的思想
何为单调栈?
解释一下:
单调栈类似单调队列,这道题中要运用到单调栈。
如下:
令f[i]为向右看齐的人的标号
6 3 2 6 1 1 2
f分别为 3 3 0 6 6 0
首先,最后一个人必然没有向右看齐的人的编号
先将最右边的人加入栈
接着,我们发现1,1比2小,先加入栈,当前f值为6
接着,又来了一个1,发现1=1,弹出1,接着发现1<2,则将1加进栈,当前f值为6
接着,来了一个6,6>2,弹出2,当前f值为0
接着,来了一个2,2<6,加入2,当前f值为3
最后,来了一个3,3>2,弹出2,将3加入栈,当前f值为3
最后的栈中有3和6
最后的答案就是3 3 0 6 6 0
每次只在栈中存数字标号,进来一个数,就把小于等于他的数全部弹出,若剩下有数,则答案是剩下的数,否则答案是0
为什么?
因为:
若x小于当前数,x不会成为答案。
这就是单调栈的用法
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <math.h> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int mod=1e9+7; 16 const int maxn=1e5+10; 17 using namespace std; 18 19 int A[maxn]; 20 int ans[maxn]; 21 stack<int> sk; 22 23 int main() 24 { 25 int n; 26 scanf("%d",&n); 27 for (int i=1;i<=n;i++) 28 scanf("%d",&A[i]); 29 for(int i=n;i>=1;i--) 30 { 31 while(!sk.empty()&&A[sk.top()]<=A[i]) 32 sk.pop(); 33 if(!sk.empty()) 34 ans[i]=sk.top(); 35 else 36 ans[i]=0; 37 sk.push(i); 38 } 39 for (int i=1;i<=n;i++) 40 printf("%d ",ans[i]); 41 return 0; 42 }