2023 rcpc
This commit is contained in:
166
2023/rcpc/d2/editorial/k-blabla-681.cpp
Normal file
166
2023/rcpc/d2/editorial/k-blabla-681.cpp
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user