290 lines
6.3 KiB
C++
290 lines
6.3 KiB
C++
#include <bits/stdc++.h>
|
|
|
|
using namespace std;
|
|
|
|
#define int long long
|
|
|
|
int n,v[200005];
|
|
int ans;
|
|
|
|
void solvell(int l,int r)///ambele in stanga
|
|
{
|
|
int mij = (l + r) / 2;
|
|
int rmax = mij + 1;
|
|
int maxst = 0,minst = 1e9;
|
|
for (int i = mij; i >= l; i--)
|
|
{
|
|
maxst = max(maxst,v[i]);
|
|
minst = min(minst,v[i]);
|
|
while (rmax <= r and v[rmax] <= maxst and v[rmax] >= minst)
|
|
rmax++;
|
|
int topr = maxst - minst + i;
|
|
int rreal = min(topr,rmax - 1);
|
|
ans += max(0ll,rreal - mij);
|
|
}
|
|
}
|
|
|
|
void solverr(int l,int r)///ambele in dreapta
|
|
{
|
|
int mij = (l + r) / 2;
|
|
int lmax = mij;
|
|
int maxdr = 0,mindr = 1e9;
|
|
for (int i = mij + 1; i <= r; i++)
|
|
{
|
|
maxdr = max(maxdr,v[i]);
|
|
mindr = min(mindr,v[i]);
|
|
while (lmax >= l and v[lmax] < maxdr and v[lmax] > mindr)
|
|
lmax--;
|
|
int topl = i - maxdr + mindr;
|
|
int lreal = max(topl,lmax + 1);
|
|
ans += max(0ll,mij - lreal + 1);
|
|
}
|
|
}
|
|
|
|
struct ura
|
|
{
|
|
int l,r,val;
|
|
};
|
|
|
|
vector<ura>queries;
|
|
|
|
void addquery(int l,int r,int val)
|
|
{
|
|
ura aux;
|
|
aux.l = l;
|
|
aux.r = r;
|
|
aux.val = val;
|
|
queries.push_back(aux);
|
|
}
|
|
|
|
int aib[200005];
|
|
vector<pair<int,int>>updates;
|
|
|
|
void update(int pos,int val)
|
|
{
|
|
for (int i = pos; i <= n; i += (i & -i))
|
|
aib[i] += val;
|
|
}
|
|
|
|
int query(int pos)
|
|
{
|
|
int x = 0;
|
|
for (int i = pos; i > 0; i -= (i & -i))
|
|
x += aib[i];
|
|
return x;
|
|
}
|
|
|
|
void upd(int pos,int val)
|
|
{
|
|
updates.push_back({pos,val});
|
|
update(pos,val);
|
|
}
|
|
|
|
void resetaib()
|
|
{
|
|
for (auto it : updates)
|
|
update(it.first,-it.second);
|
|
updates.clear();
|
|
}
|
|
|
|
bool cmp(ura A,ura B)
|
|
{
|
|
return A.val < B.val;
|
|
}
|
|
|
|
void solvequeries(int l,int r)
|
|
{
|
|
sort(queries.begin(),queries.end(),cmp);
|
|
vector<pair<int,int>>values;
|
|
int mxx = 0;
|
|
int mij = (l + r) / 2;
|
|
for (int i = mij + 1; i <= r; i++)
|
|
{
|
|
mxx = max(mxx,v[i]);
|
|
values.push_back({i - mxx,i});
|
|
}
|
|
sort(values.begin(),values.end());
|
|
int i1 = 0;
|
|
for (int i = 0; i < queries.size(); i++)
|
|
{
|
|
while (i1 < values.size() and values[i1].first <= queries[i].val)
|
|
upd(values[i1].second,1ll),i1++;
|
|
ans += query(queries[i].r) - query(queries[i].l - 1);
|
|
}
|
|
resetaib();
|
|
}
|
|
|
|
void solvelr(int l,int r)///min in stanga,max in dreapta
|
|
{
|
|
int mij = (l + r) / 2;
|
|
int maxst = 0,minst = 1e9;
|
|
vector<int>premax(r - mij + 2);
|
|
premax[1] = v[mij + 1];
|
|
for (int i = mij + 2; i <= r; i++)
|
|
premax[i - mij] = max(premax[i - mij - 1],v[i]);
|
|
int rmin = mij + 1,rmax = mij + 1;///nu se poate r < rmin fiindca nu ar mai fi max in dreapta, nu se poate r >= rmax fiindca ar fi min in dreapta
|
|
for (int i = mij; i >= l; i--)
|
|
{
|
|
maxst = max(maxst,v[i]);
|
|
minst = min(minst,v[i]);
|
|
while (rmin <= r and premax[rmin - mij] <= maxst)
|
|
rmin++;
|
|
while (rmax <= r and v[rmax] >= minst)
|
|
rmax++;
|
|
//if (l == 1 and r == 10)
|
|
// cout << i << ' ' << rmin << ' ' << rmax << '\n';
|
|
if (rmin <= rmax - 1)
|
|
{
|
|
///ma intreb cate valori intre rmin si rmax - 1 sunt valide
|
|
///o valoare e valida daca r - maxpref[r] <= l - minst
|
|
addquery(rmin,rmax - 1,i - minst);
|
|
}
|
|
}
|
|
solvequeries(l,r);
|
|
queries.clear();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct ura2
|
|
{
|
|
int l,r,val;
|
|
};
|
|
|
|
vector<ura2>queries2;
|
|
|
|
void addquery2(int l,int r,int val)
|
|
{
|
|
ura2 aux;
|
|
aux.l = l;
|
|
aux.r = r;
|
|
aux.val = val;
|
|
queries2.push_back(aux);
|
|
}
|
|
|
|
int aib2[200005];
|
|
vector<pair<int,int>>updates2;
|
|
|
|
void update2(int pos,int val)
|
|
{
|
|
for (int i = pos; i <= 2 * n; i += (i & -i))
|
|
aib2[i] += val;
|
|
}
|
|
|
|
int query2(int pos)
|
|
{
|
|
int x = 0;
|
|
for (int i = pos; i > 0; i -= (i & -i))
|
|
x += aib2[i];
|
|
return x;
|
|
}
|
|
|
|
void upd2(int pos,int val)
|
|
{
|
|
updates2.push_back({pos,val});
|
|
update2(pos,val);
|
|
}
|
|
|
|
void resetaib2()
|
|
{
|
|
for (auto it : updates2)
|
|
update2(it.first,-it.second);
|
|
updates2.clear();
|
|
}
|
|
|
|
bool cmp2(ura2 A, ura2 B)
|
|
{
|
|
return A.val < B.val;
|
|
}
|
|
|
|
void solvequeries2(int l,int r)
|
|
{
|
|
sort(queries2.begin(),queries2.end(),cmp2);
|
|
vector<pair<int,int>>values;
|
|
int mij = (l + r) / 2;
|
|
int mxx = 0;
|
|
for (int i = mij; i >= l; i--)
|
|
{
|
|
mxx = max(mxx,v[i]);
|
|
values.push_back({i + mxx,i});
|
|
}
|
|
sort(values.begin(),values.end());
|
|
int i1 = 0;
|
|
for (int i = 0; i < queries2.size(); i++)
|
|
{
|
|
while (i1 < values.size() and values[i1].first < queries2[i].val)
|
|
upd2(values[i1].second,1),i1++;
|
|
ans += (queries2[i].r - queries2[i].l + 1);
|
|
ans -= (query2(queries2[i].r) - query2(queries2[i].l - 1));
|
|
}
|
|
resetaib2();
|
|
}
|
|
|
|
void solverl(int l,int r)///min in dreapta,max in stanga
|
|
{
|
|
int mij = (l + r) / 2;
|
|
int maxdr = 0,mindr = 1e9;
|
|
vector<int>sufmax(mij - l + 2);
|
|
sufmax[mij - l + 1] = v[mij];
|
|
for (int i = mij - 1; i >= l; i--)
|
|
sufmax[i - l + 1] = max(sufmax[i - l + 2],v[i]);
|
|
int lmin = mij,lmax = mij;///nu se poate l > lmax fiindca nu ar mai fi max in stanga, nu se poate l <= lmin fiindca ar fi min in stanga
|
|
for (int i = mij + 1; i <= r; i++)
|
|
{
|
|
maxdr = max(maxdr,v[i]);
|
|
mindr = min(mindr,v[i]);
|
|
while (lmax >= l and sufmax[lmax - l + 1] < maxdr)
|
|
lmax--;
|
|
while (lmin >= l and v[lmin] > mindr)
|
|
lmin--;
|
|
//if (l == 1 and r == 9)
|
|
// cout << i << ' '<< lmin << ' ' << lmax << '\n';
|
|
if (lmin + 1 <= lmax)
|
|
{
|
|
///ma intreb cate valori intre lmin + 1 si lmax sunt valide
|
|
///o valoare e valida daca l + maxsuf[l] >= r + mindr
|
|
addquery2(lmin + 1,lmax,i + mindr);
|
|
}
|
|
}
|
|
solvequeries2(l,r);
|
|
queries2.clear();
|
|
}
|
|
|
|
void solve(int l,int r)
|
|
{
|
|
if (l > r)
|
|
return;
|
|
if (l == r)
|
|
{
|
|
ans++;
|
|
return;
|
|
}
|
|
int mij = (l + r) / 2;
|
|
solve(l,mij);
|
|
solve(mij + 1,r);
|
|
//cout << l << ' ' << r << ' ';
|
|
solvell(l,r);
|
|
//cout << ans - d1 << ' ';
|
|
solverr(l,r);
|
|
//cout << ans - d1 << ' ';
|
|
solvelr(l,r);
|
|
//cout << ans - d1 << ' ';
|
|
solverl(l,r);
|
|
//cout << ans - d1 << '\n';
|
|
}
|
|
|
|
signed main()
|
|
{
|
|
ios_base::sync_with_stdio(false);
|
|
cin.tie(NULL);
|
|
cout.tie(NULL);
|
|
cin >> n;
|
|
for (int i = 1; i <= n; i++)
|
|
cin >> v[i];
|
|
solve(1,n);
|
|
cout << ans;
|
|
return 0;
|
|
}
|