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;
}
posted @ 2019-03-22 14:22  Trimsteanima  阅读(109)  评论(0编辑  收藏  举报
Live2D