标签:lan include esc out 直接 记录 last c++ ==
给定一个环,环上 n 座山,若连接两座山的两个弧中有任何一个上没有比两座山更高的山,那么这两座山可以互相看见彼此。现在给定 n 座山的高度,求能够看见彼此信号的山的数量。
对于 x,y,如果 x!=y 我们用小的去统计大的,如果 x=y 我们把能相互看见的放在一起统计
设最高的山为 a0,也是 an,其余按顺序旋转排列
现在显然 0 和 n 可以看见所有的山
我们求出每个数前面第一个严格大于它的和右边第一个严格大于它的,位置分别记为 l,r,那么只要这两个存在,就会贡献一个 2
同时,考虑每个数和他右边第一个更大数之前的所有等大的数的贡献,假设有 c 个,那么这个数还贡献一个 c
但需要注意,如果 l,r 找不到,那么贡献直接记为 n-1
求 l,r 直接用单调栈即可,维护一个不严格单调递增的栈,每个元素被弹出时,记录一下它是被谁弹出的,这个家伙就是第一个严格比他大的
求 c,在弹栈的过程中用一个计数维护一下
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
int n, a[N], b[N], s[N], top, l[N], r[N], c[N];
signed main()
{
ios::sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> b[i];
int maxpos = max_element(b + 1, b + n + 1) - b;
for (int i = 0; i <= n; i++)
a[i] = b[(maxpos + i - 1) % n + 1];
top = 0;
int last_pop = -1, last_pop_count = 0;
for (int i = 0; i <= n; i++)
{
while (top && a[i] > a[s[top]])
{
if (last_pop == a[s[top]])
++last_pop_count;
else
last_pop_count = 0, last_pop = a[s[top]];
c[s[top]] = last_pop_count;
r[s[top]] = i, --top;
}
s[++top] = i;
if (a[i] != last_pop)
last_pop = -1, last_pop_count = 0;
}
while (top)
{
if (last_pop == a[s[top]])
++last_pop_count;
else
last_pop_count = 0, last_pop = a[s[top]];
c[s[top]] = last_pop_count;
r[s[top]] = -1, --top;
}
top = 0;
for (int i = n; i >= 0; i--)
{
while (top && a[i] > a[s[top]])
{
l[s[top]] = i, --top;
}
s[++top] = i;
}
while (top)
l[s[top]] = -1, --top;
// for (int i = 0; i <= n; i++)
// cout << a[i] << " ";
// cout << endl;
// for (int i = 0; i <= n; i++)
// cout << l[i] << " ";
// cout << endl;
// for (int i = 0; i <= n; i++)
// cout << r[i] << " ";
// cout << endl;
// for (int i = 0; i <= n; i++)
// cout << c[i] << " ";
// cout << endl;
c[0] = 0;
int ans = 0;
for (int i = 0; i < n; i++)
{
if (a[i] < a[0])
{
ans += 2;
if (l[i] == 0 && r[i] == n)
ans--;
}
ans += c[i];
}
cout << ans << endl;
}
[CF5E] Bindian Signalizing - 单调栈
标签:lan include esc out 直接 记录 last c++ ==
原文地址:https://www.cnblogs.com/mollnn/p/14406131.html