这题的意思是给一个环状的山的高度,如果两座山互相能看见便符合,求符合的对数有多少。这里l[i]为i左边第一个比i大的山的位置,r[i]为i右边第一个比i大的山的位置,v[i]为i右边在遇到比i高的山之前与i相同的山的个数.
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define maxn 1000005
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
__int64 num1[maxn], num2[maxn], n, ans;
int l[maxn], r[maxn], v[maxn];
int main(int argc, char *argv[])
{
int flag, maxs, w;
while(~scanf("%I64d", &n))
{
maxs = -1;
w = 0;
ans = 0;
mem(v, 0);
for(int i = 0;i < n;i++)
{
scanf("%I64d", &num1[i]);
if(maxs < num1[i])
{
maxs = num1[i];
flag = i;
}
}
for(int i = flag;i < n;i++)
num2[w++] = num1[i];
for(int i = 0;i < flag;i++)
num2[w++] = num1[i];
num2[w] = maxs;
for(int i = 1;i < n;i++)
{
l[i] = i - 1;
while(l[i]&&num2[i] >= num2[l[i]])
l[i] = l[l[i]];
}
for(int i = (n - 1);i >= 0;i--)
{
r[i] = i + 1;
while(r[i] != n&&num2[i] > num2[r[i]])
r[i] = r[r[i]];
if(num2[i] == num2[r[i]]&&r[i] != n)
{
v[i] = v[r[i]] + 1;
r[i] = r[r[i]];
}
}
for(int i = 1;i < n;i++)
{
ans += v[i];
ans += 2;
if(!l[i]&&r[i] == n)
ans--;
}
printf("%I64d\n", ans);
}
return 0;
}