题目:http://codeforces.com/contest/5/problem/E
题意:首都周围有n个山围成一个环,任意两座山可以看见当且仅当他们之间没有更高的山,让求有多少对山可以看见。
思路:太妙了
官方题解:http://codeforces.com/blog/entry/213
或者直接看代码
代码:
#include<iostream>
using namespace std;
const int N = 1000005;
int a[N],b[N],c[N],l[N],r[N];
int main()
{
ios_base::sync_with_stdio(false);
int n;
while(cin >> n)
{//cout <<"yyyy"<<"\n";
int maxn = 0,pos = 0;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
if(maxn < a[i])
{
maxn = a[i];
pos = i;
}//cout <<"gg"<<"\n";
}
//cout <<"hh"<<"\n";
b[n+1] = a[pos];
for(int i = 1;i <= n;i++)
b[i] = a[pos++],pos = pos > n ? pos-n : pos;
for(int i = 2;i <= n;i++)//O(n)
{
l[i] = i-1;
while(l[i] > 1 && b[i] >= b[l[i]])
l[i] = l[l[i]];
}
c[n+1] = 0;
for(int i = n;i >= 1;i--)
{
r[i] = i+1;
while(r[i] <= n && b[i] > b[r[i]])
r[i] = r[r[i]];
if(r[i] <= n && b[i] == b[r[i]])
{
c[i] = c[r[i]] + 1;
r[i] = r[r[i]];
}
}
//cout <<"SDFGS"<<"\n";
long long sum = 0;
for(int i = 2;i <= n;i++)
{
sum += c[i];
sum += 2;
if(l[i] == 1 && r[i] == n+1)
sum--;
}
cout << sum << "\n";
}
return 0;
}
// 1 2 4 5 3
//1 1 1