题意:有n座山围成一个圈,找出两座山,他们之间形成的两段圆弧任意一段中没有高于它们两个的山那么count++;
统计有多少不同对这样的组合;
思路:看别人的题解 ,先将环拆成链,从最高的山那里断开,比如5,3,7,1,4,可以断开为 7,1,4,5,3,7 在最后要加上一个最大值
然后统计每个点左边第一个大于它的山的位置和右边第一个大于它的山的位置,对于相同高度的,只考虑右边就可以(避免重复);
l[i] 存左边,r[i]存右边,s[i]记录相同的个数;
对于每个山,ans先加上s[i],如果此时l[i]==0&&r[i]==n说明左右是同一个山,ans+=1;否则不是同一个山ans+=2;
但是复杂度有点难以计算,玄学吧;
AC代码(其实是参考别人的)
#include <iostream>
#include <string.h>
#include <algorithm>
#define STD std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int maxn=1e6+10;
int a[maxn],b[maxn],l[maxn],r[maxn],s[maxn];
using namespace std;
int main()
{
STD;
int n,maxn,po;
cin>>n;
for (int i=0;i<n;i++)
cin>>a[i];
maxn=a[0];
po=0;
for (int i=1;i<n;i++)
{
if (a[i]>maxn)
{
maxn=a[i];
po=i;
}
}
for (int i=0;i<n;i++)
b[i]=a[(po+i)%n];
b[n]=b[0];
s[n]=0;
for (int i=n-1;i>=0;i--)
{
r[i]=i+1;
while (r[i]<n&&b[i]>b[r[i]])
r[i]=r[r[i]];
while (r[i]<n&&b[i]==b[r[i]])
{
s[i]=s[r[i]]+1;
r[i]=r[r[i]];
}
}
l[0]=0;
for (int i=1;i<n;i++)
{
l[i]=i-1;
while (l[i]>0&&b[i]>=b[l[i]])
l[i]=l[l[i]];
}
long long ans=0;
for (int i=0;i<n;i++)
{
ans+=s[i];
if (b[i]<b[0])
{
if (l[i]==0&&r[i]==n)
ans+=1;
else
ans+=2;
}
}
cout<<ans<<endl;
return 0;
}