保卫方案

题目地址:https://www.nowcoder.com/test/5715499/summary


时间限制:1秒

空间限制:32768K

战争游戏的至关重要环节就要到来了,这次的结果将决定王国的生死存亡,小B负责首都的防卫工作。首都位于一个四面环山的盆地中,周围的n个小山构成一个环,作为预警措施,小B计划在每个小山上设置一个观察哨,日夜不停的瞭望周围发生的情况。一旦发生外地入侵事件,山顶上的岗哨将点燃烽烟,若两个岗哨所在的山峰之间没有更高的山峰遮挡且两者之间有相连通路,则岗哨可以观察到另一个山峰上的烽烟是否点燃。由于小山处于环上,任意两个小山之间存在两个不同的连接通路。满足上述不遮挡的条件下,一座山峰上岗哨点燃的烽烟至少可以通过一条通路被另一端观察到。对于任意相邻的岗哨,一端的岗哨一定可以发现一端点燃的烽烟。 小B设计的这种保卫方案的一个重要特性是能够观测到对方烽烟的岗哨对的数量,她希望你能够帮她解决这个问题。
输入描述:
输入中有多组测试数据,每一组测试数据的第一行为一个整数n(3<=n<=10^6),为首都周围的小山数量,第二行为n个整数,依次表示为小山的高度h(1<=h<=10^9).


输出描述:
对每组测试数据,在单独的一行中输出能相互观察到的岗哨的对数。

输入例子1:
5
1 2 4 5 3

输出例子1:
7




没做出来。。。。尝试了用单调栈,但是遇到了很多坑。。。。不知道怎么做了。。。


在网上找到了一个解法,果然是用的单调栈。。。。。不过细节都处理掉了,比如连续的相同的高度之类的。。。自己写题的时候细节总是处理不好,写法不好导致代码太混乱,写一会就不想写了。。。忧伤。。。

#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
using namespace std;
const int N=1e6+10;
typedef long long lld;
 
lld cnt[N];
int ori[N],st[N];
 
void solve()
{
   int n;
   scanf("%d", &n);
 
   int hi=0;
 
   for(int i=0;i<n;++i)
   {
       scanf("%d", ori+i);
       if(i && ori[i]>ori[hi])hi=i;
   }
 
   int len=0;
   cnt[len]=1;
   st[len]=ori[hi];
   len++;
   lld sum=0;
 
   for(int i=(hi+1)%n; i!=hi; i=(i+1)%n)
   {
       while(st[len-1]<ori[i])
       {
           sum+=cnt[--len];
       }
 
       if(st[len-1]==ori[i])
       {
           sum+=cnt[len-1];
           cnt[len-1]++;
           if(len>1)sum++;
       }
       else
       {
           sum++;
           cnt[len]=1;
           st[len]=ori[i];
           len++;
       }
   }
 
   for(int i=len-1;i>0;--i)
   {
       if(i==1)
       {
           if(cnt[0]>1)
           {
               sum+=cnt[i];
           }
       }
       else sum+=cnt[i];
   }
 
   printf("%lld\n", sum);
 
}
 
int main(){
    solve();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值