一、题目描述

问题描述:给你一个数组,表示烽火台的信号值,烽火台是首尾相接的环形组成的,返回满足下列条件有多少对烽火台能两两通讯:1)相邻的烽火台能相互通讯2)不相邻的烽火台能相互通讯的条件为:两个烽火台经过的所有烽火台的信号值都不大于这两个中的最小那个。比如数组【1 2 4 3 5】相邻的【1 2】【2 3】【3 4】【4 5】【5 1】,不相邻的【5 4】可以通讯,
因为中间的3比4和5中小的要小,还有【5 2】也可以通讯,但是【3 2】【4 1】就不能相互通讯了。
所以一共返回7对

二、分析

思路:使用单调栈实现,

1)遍历数组找到最大的元素压入栈底,后面入栈保证栈底到栈顶从大到小,栈中记录元素值和当前值出现的次数

2)如果遇到入栈元素比栈顶元素大,出栈结算,下面详细介绍结算的过程

3)如果遇到相同的元素则继续入栈,栈中元素出现的次数加1即可,比如下面这个例子

4)现在看一种普遍的情况,总结出出栈结算的方式。

5)如果没有出栈的情况或者遍历完了元素也没有出栈的情况

6)现在考虑只有最后两条记录的时候,有两种情况,分别是栈底元素出现次数≥2和小于2的情况,看图

总结:还没遍历完数组压栈和弹栈过程中,C(times,2)+times*2.
遍历完数组之后,弹栈时,相同元素内部还是有C(times,2)对,
如果栈底元素times大于等于2结算方式同上,为1则为C(times,2) + times*1,
因为times为1的时候顺时针和逆时针都和该元素成对,算一次即可

三、代码实现

#include<iostream>
#include<stack>
using namespace std;class Data {
public:int val;int times;Data(int num) :val(num), times(1) {}
};
long getInerNum(int n) {//如果n为1则返回0个,否则就是C(times,2),C(k,2)=k!/((k-2)!*2!) = k(k-1)/2return n == 1L ? 0L : (long)n*(long)(n - 1) / 2L;
}
long communication(int arr[], int arr_len) {if (arr == NULL || arr_len < 2) {//数组没有元素或者只有一个元素,返回0对return 0;}int max_index = 0;for (int i = 0; i < arr_len; ++i) {//在数组中找最大值的位置max_index = arr[max_index] > arr[i] ? max_index : i;}int value = arr[max_index];//爱的魔力转圈圈,如果到达最后一个则下一个从0开始,否则为max_index+1int next_index = max_index + 1 > arr_len - 1 ? 0 : max_index + 1;//从最大值位置的下一个开始遍历long res = 0L;stack<Data*> sta;sta.push(new Data(value));while (next_index!=max_index) {//如果next_index回到max_index表示我们遍历结束value = arr[next_index];while (value > sta.top()->val) {//这里采用最大值打底,所以栈不可能弹成空int times = sta.top()->times;res += (getInerNum(times) + times * 2);sta.pop();}//下面表示无法弹了,无法弹的原因有两个,小于或等于栈顶元素if (!sta.empty() && sta.top()->val == value)sta.top()->times++;elsesta.push(new Data(value));next_index = next_index+1 > arr_len - 1 ? 0: next_index + 1;//更新next_index}while (!sta.empty()) {int times = sta.top()->times;sta.pop();res += getInerNum(times);//如果不是倒数第二和倒数第一,则固定就是C(times,2)和times*2if (!sta.empty()) {res += times;if (sta.size() > 1) {//pop了之后还大于1表示栈中有3个以上元素,再加一次timesres += times;}else//否则只有2个元素,只有两个元素的时候考虑栈底元素的times是否大于,是则再加一次,否则不加res += sta.top()->times > 1 ? times : 0;}}return res;
}
int main() {int n;while (cin >> n) {int* arr = new int[n];for (int i = 0; i < n; ++i) {cin >> arr[i];}cout << communication(arr,n) << endl;}
}

烽火台问题(单调栈应用)相关推荐

  1. 算法学习12: 单调队列和单调栈

    算法学习12: 单调队列和单调栈 单调队列 单调队列解决的问题: 窗口内最大/最小值的更新结构 单调队列的结构和操作 单调队列的应用 题目一: 生成窗口最大值数组[leetcode 239](http ...

  2. POJ2796 Feel Good(单调栈)

    题意: 给出一列数据,要求一个区间内最小值与区间内数据总和乘积最大值 要点: 还是单调栈,这次我自己写的,先做了几题比较简单的果然还是有效果的,这题也是一样,按点遍历,网上大神做的是直接遍历一次即可, ...

  3. 【单调栈 前缀和 异或】7.21序列求和

    还要再细细思考的奇妙思路 题目描述 小A最近喜欢上了关于区间max的问题.她定义一个区间的价值是max(ai)(l<=i<=r)∗(alxoral+1xor...xorar)max(ai) ...

  4. 栈与队列7——单调栈结构(进阶问题)

    题目 一个含有重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置,返回所有相应的信息. 举例:arr={3,4,1,5,6,2,7},返回如下的二维数组作为结果:{{ ...

  5. 栈与队列7——单调栈结构(初阶问题)

    题目 一个不含有重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置,返回所有相应的信息. 举例:arr={3,4,1,5,6,2,7},返回如下的二维数组作为结果:{ ...

  6. 单调栈 or 线段树扫描线 ---- E. Delete a Segment [单调栈+二分] [扫描线处理空白位置的技巧乘2]

    题目链接 题目大意: 给出nnn个线段代表集合,现在问若可以将其中任意一个线段删除,则能够形成最多多少个独立的集合(取并集后) 解题思路1: 首先我们先对线段按照起点排序 那么我们枚举删除的线段iii ...

  7. 后缀数组 ---- 2018~2019icpc焦作H题[后缀数组+st表+二分+单调栈]

    题目链接 题目大意: 给出nnn个数,定义f[l,r]f[l,r]f[l,r]表示 区间[l,r][l,r][l,r]的最大值,求所有 子区间的最大值的和,要求相同的子区间只能算一次 比如数列 5 6 ...

  8. [Ahoi2013]差异[后缀数组+单调栈]

    链接 解题思路:很明显前面∑1<=i<j<=nlen(Ti)+len(Tj)\sum_{1<=i<j<=n}len(T_i)+len(T_j)∑1<=i< ...

  9. 【每日训练】2020/11/8(规律 + 二进制、单调栈 + 前缀和,后缀和、bitset + 枚举)

    整理的算法模板合集: ACM模板 目录 1. NC 打铁的箱子(规律 + 二进制) 2. NC 最优屏障(单调栈 + 前缀和,后缀和) 3. CF993C Careful Maneuvering(bi ...

最新文章

  1. leetCode C++ 49. 字母异位词分组 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
  2. (转载)一套完整的UI设计规范手册(IOS版)
  3. 也可以看看GCD(杭州电2504)(gcd)
  4. iQOO Neo5搭载66W超快闪充:30分钟回血!
  5. 设计模式1-简单工厂模式
  6. 通用程序算法和数据结构_了解通用数据结构
  7. Python小游戏-接苹果
  8. matlab矩阵除法用python改写
  9. 第三方支付api接口是什么?
  10. 如何选一款软件助力企业腾飞
  11. 基于微信小程序的毕业设计题目(30)php物业维修报修小程序(含开题报告、任务书、中期报告、答辩PPT、论文模板)
  12. 多任务学习综述:推荐系统多任务学习(multitask)的实战总结和常见问题(一)
  13. ndnSIM学习(十)——apps之ndn-producer.cpp和ndn-consumer.cpp源码分析
  14. 小程序获取用户微信步数
  15. tokenizer.encode、tokenizer.tokenize、tokenizer.encode_plus的用法差异
  16. springMVC实现jsonp的跨域请求
  17. python nameerror什么意思_我用Python编写的GTIN程序中的“NameError”是什么意思?
  18. c语言n阶方阵,如何用C语言编出一个N阶螺旋方阵?
  19. matlab中离散信号模型
  20. HEIC图片格式如何快速转换呢?

热门文章

  1. MATLAB图像置乱混沌加密解密设计
  2. 2021-09-10 文件上传时,文件的格式的区别,如application/x-www-form-urlencoded
  3. 小提琴机器人拉法_小提琴机器人拉法_小提琴艺术的形成与发展
  4. 成功打造工业品牌的三大基石
  5. 使用eop烧写裸板程序步骤
  6. vr安全教育消防安全循序渐进地开展火灾知识、技能及实训教学
  7. KVM虚拟化- KVM虚拟化介绍
  8. 变频器LED显示灯闪烁_长海力士乐变频器维修
  9. 华钜跨境电商ERP系统是什么
  10. 爬虫之成都单片机实习岗