CF5E Bindian Signalizing

题目

这题目是真的很水,洛谷给他紫题也差不多算恶意评分了吧233
这种一眼切的题改了很长时间,不是什么n-1搞错,就是什么and打成or,所以写这篇博客给自己长个记性QWQ
题意:n座山组成一个环,相连的圆弧上其他山它们高那么这两座山能互相看到,求能看到的山的组数。
题解:设left[i]表示左边第一个比i高的位置,同理right[i]表示右边第一个比i高的位置。count[i]表示i到right[i]区间(i不在区间内,right[i]在)内高度等于i的山的个数。

注意要用long long

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000010;
long long ans;
int n, p;
int leftt[MAXN], rightt[MAXN], a[MAXN], b[MAXN], countt[MAXN];
inline int read() {
    char ch; bool f = false; int res = 0;
    while (((ch = getchar()) < '0' || ch > '9') && ch != '-');
    if (ch == '-') f = true; else res = ch - '0';
    while ((ch = getchar()) >= '0' && ch <= '9') res = (res << 3) + (res << 1) + ch - '0';
    return f? ~res + 1 : res;
}
int main() {
    n = read();
    for (int i = 0; i < n; ++ i) {
        a[i] = read();
    }
    p = 0;
    for (int i = 1; i <= n; ++ i) //find max
        if (a[i] > a[p])
            p = i;
    for (int i = 0; i <= n; ++ i) // link
        b[i] = a[(i + p) % n];
    for (int i = 1; i <= n; ++ i) {
        leftt[i] = i - 1;
        while (leftt[i] && b[i] >= b[leftt[i]])
            leftt[i] = leftt[leftt[i]];
        //printf("%d\n",leftt[i]);
    }
    for (int i = n - 1; i >= 0; i --) {
        rightt[i] = i + 1;
        while (rightt[i] < n && b[i] > b[rightt[i]])
            rightt[i] = rightt[rightt[i]];
        if (rightt[i] < n && b[i] == b[rightt[i]]) {
            countt[i] = countt[rightt[i]] + 1;
            rightt[i] = rightt[rightt[i]];
        }
    }
    for (int i = 0; i < n; ++ i) {
        ans += countt[i];
        if (b[i] < b[0]) {
            ans += 2;
            if (!leftt[i] && rightt[i] == n)
                ans --;
        }
        //printf("%lld\n", ans);
    }
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wjnclln/p/10577987.html