Description
对家庭菜园有兴趣的 JOI 君每年在自家的田地中种植一种叫做 IOI 草的植物. JOI 君的田地沿东西方向被划分为 \(n\) 个区域, 由西到东标号为 \(1 - n\). IOI 草一共有 \(n\) 株, 每个区域 种植着一株. 在第 \(i\) 个区域种植的 IOI 草, 在春天的时候高度会生长至 \(h_i\), 此后便不再生长.
为了观察春天的样子而出行的 JOI 君注意到了 IOI 草的配置与预定的不太一样. IOI 草是一种 非常依靠阳光的植物, 如果某个区域的 IOI 草的东侧和西侧都有比它高的 IOI 草存在, 那么 这株 IOI 草就会在夏天之前枯萎. 换句话说, 为了不让任何一株 IOI 草枯萎, 需要满足以下条件:
对于任意 \(2 \leq i \leq n-1\), 以下两个条件至少满足一个:
- \(\forall 1 \leq j \leq i-1, h_j \leq h_i\)
- \(\forall i+1 \leq k \leq n, h_k \leq h_i\)
IOI 草是非常昂贵的, 为了不让 IOI 草枯萎, JOI 君需要调换 IOI 草的顺序. IOI 草非常非常的 高大且纤细的植物, 因此 JOI 君每次只能交换相邻两株 IOI 草. 也就是说, JOI 君每次需要选择一个整数 \(i (1 \leq i \leq n-1)\), 然后交换第 \(i\) 株 IOI 草和第 \(i+1\) 株 IOI 草. 随着 夏天临近, IOI 草枯萎的可能性越来越大, 因此 JOI 君想知道让所有 IOI 草都不会枯萎的最少操作次数.
现在给出田地的区域数, 以及每株 IOI 草的高度, 请你求出让所有 IOI 草的不会枯萎的最少操作次数.
Input
第一行一个正整数 \(n\), 代表田地被分为了 \(n\) 个区域.
接下来 \(n\) 行, 第 \(i\) 行 \((1 \leq i \leq n)\) 一个整数 \(h_i\), 表示第 \(i\) 株植物在 春天时的高度.
Output
输出一行一个整数, 表示最少需要的操作次数.
Sample Input
6
2
8
4
5
3
6
Sample Output
3
Data Range
对于所有数据, 满足:\(3 \leq n \leq 3 \times 10^5, 1 \leq h_i \leq 10^9\)
Explanation
首先一个足够高的植物一定不会影响到更高的植物对吧......
然后极端地来看像最高的那一棵到哪里都会招人恨对不对......
然后贪心地我们发现一棵植物必须要么向左要么向右移动, 移动的距离就是左边比他高一点 的最靠左的那一棵植物, 右边同理. 然后发现其实就是每一次贪心一下, 用树状数组或者线段树记录一下就可以了.
Source Code
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long lli;
const int maxn = 300100;
class BinaryIndexedTree
{
public:
int n, arr[maxn];
void change(int x, int v)
{
for (; x > 0; x -= x&-x)
arr[x] += v;
return ;
}
int query(int x)
{
int res = 0;
for (; x <= n; x += x&-x)
res += arr[x];
return res;
}
void clear(void)
{
n = 0;
memset(arr, 0, sizeof(arr));
return ;
}
} bit;
int n, n__, a[maxn];
pair<int, int> b[maxn];
int l[maxn], r[maxn];
int main(int argc, char** argv)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &b[i].first);
b[i].second = i;
}
sort(b + 1, b + n + 1);
n__ = 0;
for (int i = 1; i <= n; i++) {
if (i == 1 || b[i].first != b[i-1].first)
n__ += 1;
a[b[i].second] = n__;
}
// Inserting
bit.n = n__;
for (int i = 1; i <= n; i++) {
bit.change(a[i], 1);
l[i] = bit.query(a[i] + 1);
}
bit.clear();
// Inserting, reversed.
bit.n = n__;
for (int i = n; i >= 1; i--) {
bit.change(a[i], 1);
r[i] = bit.query(a[i] + 1);
}
// Generate output
lli res = 0;
for (int i = 1; i <= n; i++)
res += min(l[i], r[i]);
printf("%lld\n", res);
return 0;
}