Codeforces 547B Mike and Feet(单调栈)

题目链接:http://codeforces.com/problemset/problem/547/B

题目大意:
有一个长度为n的序列,序列有长度为1...n的连续子序列,一个连续子序列里面最小的值称作这个子序列的子序列的strength,
要求出每种长度的连续子序列的最大的strength。
解题思路:
可以用栈求出每个点的l[i],表示值小于当前位置并且在左侧的最接近这个点的位置。
同理可以求出r[i],表示值小于当前位置并且在右侧侧的最接近这个点的位置。
求l[i]过程如下:
stack s // initially empty
for i = 1 to n
while s is not empty and a[s.top()] >= a[i]
do s.pop()
if s is empty
then l[i] = 0
otherwise
l[i] = s.top()
s.push(i)
接下来,我们遍历每个位置i,令len=r[i]-l[i]-1,则ans[len]=min(a[i],ans[len])
可以理解为在r[i]-1~l[i]+1这块长度为len的区间上,最小的就是a[i],所以ans[len]与a[i]比较。
最后还要从len=n-1~1遍历,令ans[len]=max(ans[len],a[len+1])。
为什么要这么做?
因为不这样做,如1 2 3 2 1这组样例,只能求出ans[1]、ans[3]、ans[5],像ans[2]、ans[4]都是空的。
这样做的意义就是如果ans[len]为空,则把ans[len+1]的值给它。
为什么是ans[len+1]的值,首先ans[len]>=ans[len+1],假设我们有一个长度为len+1的只有x~y的区间,min=2,则a[len+1]=2,
假设a[len]会大于a[len+1],那么必定存在x+1~y或者x~y-1的区间且min>2,但是如果ans[len-1]为空则说明没有这样的区间
所以取ans[len]=ans[len+1]。

代码

 1 #include<bits/stdc++.h>
 2 #define lc(a) (a<<1)
 3 #define rc(a) (a<<1|1)
 4 #define MID(a,b) ((a+b)>>1)
 5 #define fin(name)  freopen(name,"r",stdin)
 6 #define fout(name) freopen(name,"w",stdout)
 7 #define clr(arr,val) memset(arr,val,sizeof(arr))
 8 #define _for(i,start,end) for(int i=start;i<=end;i++)
 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
10 using namespace std;
11 typedef long long LL;
12 const int N=2e5+5;
13 const int INF=0x3f3f3f3f;
14 const double eps=1e-10;
15
16 int l[N],r[N],a[N],ans[N];
17 stack<int>sk;
18
19 int main(){
20     FAST_IO;
21     int n;
22     cin>>n;
23     for(int i=1;i<=n;i++){
24         cin>>a[i];
25     }
26     for(int i=1;i<=n;i++){
27         while(!sk.empty()&&a[sk.top()]>=a[i])
28             sk.pop();
29         if(!sk.empty())
30             l[i]=sk.top();
31         else
32             l[i]=0;
33         sk.push(i);
34     }
35     while(!sk.empty()) sk.pop();
36     for(int i=n;i>=1;i--){
37         while(!sk.empty()&&a[sk.top()]>=a[i])
38             sk.pop();
39         if(!sk.empty())
40             r[i]=sk.top();
41         else
42             r[i]=n+1;
43         sk.push(i);
44     }
45     for(int i=1;i<=n;i++){
46         int len=r[i]-l[i]-1;
47         ans[len]=max(a[i],ans[len]);
48     }
49     for(int i=n-1;i>=1;i--){
50         ans[i]=max(ans[i],ans[i+1]);
51     }
52     for(int i=1;i<=n;i++){
53         cout<<ans[i]<<" ";
54     }
55     cout<<endl;
56     return 0;
57 }

原文地址:https://www.cnblogs.com/fu3638/p/9892324.html

时间: 2024-08-28 17:19:13

Codeforces 547B Mike and Feet(单调栈)的相关文章

Codeforces 547B. Mike and Feet[单调栈/队列]

这道题用单调递增的单调栈维护每个数能够覆盖的最大区间即可. 对于   1 2 3 4 5 4 3 2 1 6 这组样例, 1能够覆盖的最大区间是10,2能够覆盖的最大区间是7,以此类推,我们可以使用单调栈来实现这种操作. 具体看代码: *Code: #include<bits/stdc++.h> using namespace std; int n,l[200005],r[200005],ans[200005],a[200005]; int stk[200005],top=0; void so

Codeforces548D:Mike and Feet(单调栈)

Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high. A group of bears

Codeforces Round #305 (Div. 2)D---Mike and Feet(单调栈)

Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high. A group of bears

cf 547B. Mike and Feet dp

题意: n个矩阵排成一排,n<=2e5,高度分别为hei[i],宽度为1 对于一些连续的矩阵,矩阵的size为矩阵的个数,矩阵的strength为这些矩阵中高度最低的那一个高度 求:for each x such that 1 ≤ x ≤ n the maximum strength among all groups of size x. 对于每一个矩阵,我们先求出这个矩阵的l,r l表示这个矩阵左边最靠近它的小于它的矩阵的下标 r表示这个矩阵右边最靠近它的小于它的矩阵的下标 即在区间(l,r)

CodeForces 548D 单调栈

Mike and Feet Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 548D Appoint description: Description Mike is the president of country What-The-Fatherland. There are n bears living in this

Codeforces Round #305 (Div. 1) B. Mike and Feet

Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high. A group of bears

Educational Codeforces Round 23 D. Imbalanced Array(单调栈)

题目链接:Educational Codeforces Round 23 D. Imbalanced Array 题意: 给你n个数,定义一个区间的不平衡因子为该区间最大值-最小值. 然后问你这n个数所有的区间的不平衡因子和 题解: 对每一个数算贡献,a[i]的贡献为 当a[i]为最大值时的 a[i]*(i-l+1)*(r-i+1) - 当a[i]为最小值时的a[i]*(i-l+1)*(r-i+1). 计算a[i]的l和r时,用单调栈维护.具体看代码,模拟一下就知道了. 然后把所有的贡献加起来.

set+线段树 Codeforces Round #305 (Div. 2) D. Mike and Feet

题目传送门 1 /* 2 题意:对于长度为x的子序列,每个序列存放为最小值,输出长度为x的子序列的最大值 3 set+线段树:线段树每个结点存放长度为rt的最大值,更新:先升序排序,逐个添加到set中 4 查找左右相邻的位置,更新长度为r - l - 1的最大值,感觉线段树结构体封装不错! 5 详细解释:http://blog.csdn.net/u010660276/article/details/46045777 6 其实还有其他解法,先掌握这种:) 7 */ 8 #include <cstd

Codeforces 802I Fake News (hard) (SA+单调栈) 或 SAM

原文链接http://www.cnblogs.com/zhouzhendong/p/9026184.html 题目传送门 - Codeforces 802I 题意 求一个串中,所有本质不同子串的出现次数的平方和. $|s|\leq 10^5$ 题解 首先,这一题用$SAM$做就是模板题,比较简单. 但是,本着练一练$SA$的心态,我开始了$SA+单调栈$的苦海. 真毒瘤. 这里讲一讲$SA$的做法,也是经典的做法. $SA$闭着眼睛先写了再说. 首先,我们考虑出现次数大于$1$次的子串. 考虑按