单调栈维护连续区间2019.1.18模拟赛T2 浇花

Posted qin-wei-kai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单调栈维护连续区间2019.1.18模拟赛T2 浇花相关的知识,希望对你有一定的参考价值。

这道题是一道单调栈的题

技术分享图片
 1 题目描述
 2 JDFZ在餐厅门前种了一排nn棵花,每棵花都有一个高度。浇花大爷会枚举所有的区间,然后从区间中找出一个高度最矮的花进行浇水。由于浇花大爷浇完水之后就精疲力竭了,所以请你帮助他计算每棵花都被浇了几次水。
 3 
 4 输入格式
 5 第一行一个整数nn。 第二行nn个整数,分别表示每棵花的高度。
 6 
 7 输出格式
 8 一行nn个整数用空格隔开,分别表示每棵花被浇了几次水。
 9 
10 样例一
11 input
12 3
13 1 3 5
14 output
15 3 2 1
16 样例解释
17 浇花大爷枚举到了6个区间分别是[1], [3], [5], [1 3], [3 5], [1 3 5],对应的最矮的花的高度是1, 3, 5, 1, 3, 118 限制与约定
19 对于40%的数据,n≤1000n≤1000
20 对于100%的数据,n≤1000000,保证每棵花的高度都不相同且≤231n≤1000000,保证每棵花的高度都不相同且≤231
21 时间限制:1s1s
22 空间限制:256MB
View Code

这道题能看出他必须要是连续的区间

首先是一个结论,就是假如一个数左面能达到n个数,右面能达到m个数,那么他的区间个数是(n+1)*(m+1)

给出证明

第一种

第一类当前数只和左面形成区间,区间数为m

第二类只和右面,同理方案数为n

第三类左右都和,方案数为nm

第四类自己就是一个区间,也就是1

加在一起,就是(n+1)*(m+1)得证

第二种

直接脑补,左面有n+1个位置可选,右面m+1个,乘在一起得证

那么现在问题就是怎么维护一个数他的左右都能达到哪里?

做法是单调栈

我们维护一个单调递减栈,

首先是右面能达到哪里,从前向后进栈,当这个数来了,从栈顶开始,把数一个个顶掉,这时被顶掉的的数的r值即为i-1,为什么呢,因为假如你在这个时候被后面顶掉了,说明就恰好这个时候后面的数比你小了,你的能力只够你达到这个数的前一个位置

然后左面的就很好理解了,从后往前进栈,然后l值变成i+1就ok

注意一点,就是最后在栈里,还是有一些数没有被顶掉,意味着这些数是可以坚持到最后的,把他们的值改成1或者n

代码在此

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 int n;
 7 int flw[1000000+100];
 8 int st1[1000000+100],st2[1000000+100];
 9 ll r[1000000+100],l[1000000+100];
10 int top1,top2;
11 int main()
12 {
13     freopen("flw.in","r",stdin);
14     freopen("flw.out","w",stdout);
15     scanf("%d",&n);
16     for(int i=1;i<=n;i++)
17         scanf("%d",&flw[i]);
18     st1[++top1]=1;
19     for(int i=2;i<=n;i++)
20     {
21         while(flw[i]<flw[st1[top1]]&&top1)
22             r[st1[top1--]]=i-1;
23         st1[++top1]=i;
24     }
25     while(top1)r[st1[top1--]]=n;
26     st2[++top2]=n;
27     for(int i=n-1;i>=1;i--)
28     {
29         while(flw[i]<flw[st2[top2]]&&top2)
30             l[st2[top2--]]=i+1;
31         st2[++top2]=i;
32     }
33     while(top2)l[st2[top2--]]=1;
34     for(int i=1;i<=n;i++)
35         printf("%lld ",(r[i]-i+1)*(i-l[i]+1));
36     fclose(stdin);
37     fclose(stdout);
38     return 0;
39 }
40 /*
41 5
42 3 1 2 5 4
43 */
44 /*
45 对于40%的数据,n <= 1000
46 对于100%的数据,n <= 1000000,保证每棵花的高度都不相同
47 */

 

以上是关于单调栈维护连续区间2019.1.18模拟赛T2 浇花的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode84. 柱状图中最大的矩形(单调栈)

poj2796 维护区间栈//单调栈

bzoj5089最大连续子段和 分块+单调栈

2/9 康托展开+单调队列+单调栈(模拟栈)

单调栈&单调队列

单调队列与单调栈作用