【Luogu P2866】[USACO06NOV]Bad Hair Day S


[USACO06NOV]Bad Hair Day S

洛谷题面

题目大意:

给定有 \(n\) 个数的数组 \(a_i\),找到在 \(i\) 之后的第一个大于 \(a_i\) 的数 \(a_j\),那么 \(a_i\) 能造成 \(j-i\) 贡献。求总贡献。

思路:

倒着跑单调栈。

代码:

const int N = 8e4 + 10;

inline ll Read() {
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n;
ll a[N];
ll q[N], t, ans;

int main() {
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	n = Read ();
	for (int i = 1; i <= n; i++) a[i] = Read();
	for (int i = n; i; i--) {
		for (; t && a[q[t]] < a[i]; t--);
		if (!t) ans += n - i;
		else ans += q[t] - i - 1;
		q[++t] = i;
	}
	printf ("%lld\n", ans);
	return 0;
}