2023 rcpc

This commit is contained in:
2024-04-22 16:45:09 +03:00
parent a0ddb657b7
commit 156202ada0
61 changed files with 4462 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
#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);
}