166 lines
3.5 KiB
C++
166 lines
3.5 KiB
C++
#include <bits/stdc++.h>
|
|
|
|
#define int long long
|
|
|
|
using namespace std;
|
|
|
|
struct rmq
|
|
{
|
|
vector<vector<int>> rmq;
|
|
vector<int> lg;
|
|
void build(vector<int> a)
|
|
{
|
|
int n = a.size() - 1;
|
|
lg = vector<int>(n + 1);
|
|
for (int i = 2; i <= n; ++i)
|
|
{
|
|
lg[i] = lg[i / 2] + 1;
|
|
}
|
|
rmq = vector<vector<int>>(n + 1, vector<int>(lg[n] + 1));
|
|
for (int i = 1; i <= n; ++i)
|
|
{
|
|
rmq[i][0] = a[i];
|
|
}
|
|
for (int j = 1; j <= lg[n]; ++j)
|
|
{
|
|
for (int i = 1; i + (1 << j) - 1 <= n; ++i)
|
|
{
|
|
rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
|
|
}
|
|
}
|
|
}
|
|
int query(int st, int dr)
|
|
{
|
|
int pow_2 = lg[dr - st + 1];
|
|
return min(rmq[st][pow_2], rmq[dr - (1 << pow_2) + 1][pow_2]);
|
|
}
|
|
};
|
|
|
|
const int nmax = 2e5;
|
|
const int vmax = 2e5;
|
|
|
|
struct aib
|
|
{
|
|
int n;
|
|
vector<int> a;
|
|
void resize(int _n)
|
|
{
|
|
n = _n;
|
|
a = vector<int>(n + 1);
|
|
}
|
|
void update(int pos, int val)
|
|
{
|
|
for (int i = pos; i <= n; i += i & (-i))
|
|
{
|
|
a[i] += val;
|
|
}
|
|
}
|
|
void clear(int pos)
|
|
{
|
|
for (int i = pos; i <= n; i += i & (-i))
|
|
{
|
|
a[i] = 0;
|
|
}
|
|
}
|
|
int query(int pos)
|
|
{
|
|
if (pos < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
int ans = 0;
|
|
for (int i = pos; i; i -= i & (-i))
|
|
{
|
|
ans += a[i];
|
|
}
|
|
return ans;
|
|
}
|
|
};
|
|
vector<int> a;
|
|
aib tree;
|
|
rmq adam;
|
|
int divide(int st, int dr)
|
|
{
|
|
if (st == dr)
|
|
{
|
|
return 1;
|
|
}
|
|
int mid = (st + dr) / 2;
|
|
int ans = divide(st, mid) + divide(mid + 1, dr);
|
|
int p1 = mid + 1, p2 = mid + 1;
|
|
int maxi = 0, mini = INT_MAX;
|
|
for (int i = mid; i >= st; --i)
|
|
{
|
|
maxi = max(maxi, a[i]);
|
|
mini = min(mini, a[i]);
|
|
while (p2 <= dr && a[p2] <= maxi)
|
|
{
|
|
tree.update(adam.query(mid + 1, p2) + (p2 - mid), 1);
|
|
p2++;
|
|
}
|
|
while (p1 <= dr && a[p1] >= mini)
|
|
{
|
|
tree.update(adam.query(mid + 1, p1) + (p1 - mid), -1);
|
|
p1++;
|
|
}
|
|
int l = p1, r = p2 - 1;
|
|
if (l <= r)
|
|
{
|
|
ans += tree.query(maxi - (mid - i + 1) + 1);
|
|
}
|
|
int cnt = min(l, r + 1) - (mid + 1);
|
|
ans += max(0ll, min(cnt, maxi - mini + 1 - (mid - i + 1)));
|
|
}
|
|
|
|
for (int i = mid + 1; i <= dr; ++i)
|
|
{
|
|
tree.clear(adam.query(mid + 1, i) + (i - mid));
|
|
}
|
|
|
|
p1 = mid, p2 = mid;
|
|
maxi = 0, mini = INT_MAX;
|
|
for (int i = mid + 1; i <= dr; ++i)
|
|
{
|
|
maxi = max(maxi, a[i]);
|
|
mini = min(mini, a[i]);
|
|
while (p2 >= st && a[p2] < maxi)
|
|
{
|
|
tree.update(adam.query(p2, mid) + (mid - p2 + 1), 1);
|
|
p2--;
|
|
}
|
|
while (p1 >= st && a[p1] >= mini)
|
|
{
|
|
tree.update(adam.query(p1, mid) + (mid - p1 + 1), -1);
|
|
p1--;
|
|
}
|
|
int l = p2 + 1, r = p1;
|
|
if (l <= r)
|
|
{
|
|
ans += tree.query(maxi - (i - mid) + 1);
|
|
}
|
|
|
|
int cnt = mid - max(l - 1, r);
|
|
ans += max(0ll, min(cnt, maxi - mini + 1 - (i - mid)));
|
|
}
|
|
|
|
for (int i = mid; i >= st; --i)
|
|
{
|
|
tree.clear(adam.query(i, mid) + (mid - i + 1));
|
|
}
|
|
|
|
return ans;
|
|
}
|
|
int32_t main()
|
|
{
|
|
cin.tie(nullptr)->sync_with_stdio(false);
|
|
int n;
|
|
cin >> n;
|
|
a = vector<int>(n + 1);
|
|
for (int i = 1; i <= n; ++i)
|
|
{
|
|
cin >> a[i];
|
|
}
|
|
adam.build(a);
|
|
tree.resize(nmax + vmax);
|
|
cout << divide(1, n);
|
|
} |