小B负责首都的防卫工作。
首都处于一个四面环山的盆地中,周围的n个小山构成一个环,作为预警措施,小B计划在每个小山上设置一个观察哨,日夜不停的瞭望周围发生的情况。
一旦发生外敌入侵事件,山顶上的岗哨将点燃烽烟。
若两个岗哨所在的山峰之间的那些山峰,高度都不大于这两座山峰,且这两个山峰之间有相连通路,则岗哨可以观察到另一个山峰上的烽烟是否点燃。
由于小山处于环上,任意两个小山之间存在两个不同的连接通路。满足上述不遮挡的条件下,一座山峰上岗哨点燃的烽烟至少可以通过一条通路被另一端观察到。
对于任意相邻的岗哨,一端的岗哨一定可以发现一端点燃的烽烟。
小B设计的这种保卫方案的一个重要特性是能够观测到对方烽烟的岗哨对的数量,她希望你能够帮她解决这个问题。
输入
输入中有多组测试数据。每组测试数据的第一行为一个整数n(3<=n<=10^6),为首都周围的小山数量,第二行为n个整数,依次表示小山的高度h,(1<=h<=10^9)。
输出
对每组测试数据,在单独的一行中输出能相互观察到的岗哨的对数。
样例输入
5
1 2 4 5 3
样例输出
7
算法思想:
此题可以理解为在两个山峰之间的山峰都比两端低时,两端山峰就是一对,现在就是求有多少对?此题可以转为环形链表中,一个数求他左右两边离他最近且大于他的数。
(1,2)(1,3)(2,3)(2,4)(4,5)(3,4)(3,5)
可以看出最高和次高可以组成一对,其他数据都能有两个相邻最大值,所以此问题通解(n-2)*2+1。
找出一个数左右最近的大于他的数,可以用单调栈实现。我们设定单调栈中,从栈顶到栈底依次变大。
假设有数 5 2 1 4 3 7
先放5,2小于5,放2,1小于2,放1,4大于1,则1弹出,1的弹出是由于4,所以4是1右边临近的大于他的数,2在1下面,所以2是1左面临近大于他的数。相同原理2弹出,4进,3进,7进时同理弹出3,4,5
左 右
1 2 4
2 5 4
3 4 7
4 5 7
5 null 7
7 null null
总对数=4*2+1。此算法复杂度可以达到O(n),遍历算法O(n^2)
以上算法只适用于,山峰高度都各不相等的情况下,若有相等则:一次遍历将相邻相等山峰合并,二次遍历找最大值开始压栈
将3个5压入,7个3压入,当6个4压入时,7个3要出栈。7个3中,自己有对,与3相邻的4,可以看到每个3,所以有7对,5与4同理有7对,
共7*6/2+7+7。
当压入数据与栈顶数据相同,则只需合并个数即可。
没有数据入栈时,只需依次出栈,
纠正上图一个错误,对于7产生的个数,少加了一个12.因为只剩下7和10的时候,从10看向7和从7看向10是不一样的所以要加两次12
6是最后一个进栈的数,他要和栈底的数产生对数。
JAVA版
package problems_2017_07_26;