http://cplusoj.com/d/senior/p/SS240709D
假设现在只有 [ 1 , x ] [1,x] [1,x]
考虑一个数的贡献区间为 r − l − 1 r-l-1 r−l−1, l , r l,r l,r 为左右第一个比它大的数的坐标
此时的答案是 ∑ r − ∑ l − x \sum r-\sum l-x ∑r−∑l−x。我们不妨先算 ∑ r \sum r ∑r,再reverse一下
要维护每个东西右边第一个比它大的东西,而且要维护还是相对坐标,考虑这个东西加入会有什么影响?
- 它自己是 x + 1 x + 1 x+1
- 它右边全部 + 1 +1 +1
- 它左边全部对 x x x 取min
上面三个东西直接拿吉司机维护即可
#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#define debag(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#define debag(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
//#define mo
#define N 200010
int n, m, i, j, k, T;
namespace Sol {
#define mid ((l + r) >> 1)
#define ls (k << 1)
#define rs (k << 1 | 1)
int mp[N];
struct Segment_tree {
int len[N << 2], slen[N << 2], sm[N << 2], d1[N << 2], d2[N << 2];
int mx1[N << 2], mx2[N << 2];
void push_down(int k) {
int l = ls, r = rs;
if(mx1[l] == mx1[r]) {
mx1[l] += d1[k]; mx1[r] += d1[k];
mx2[l] += d2[k]; mx2[r] += d2[k];
sm[l] += d1[k] * len[l]; sm[r] += d1[k] * len[r];
sm[l] += d2[k] * slen[l]; sm[r] += d2[k] * slen[r];
d1[l] += d1[k]; d1[r] += d1[k];
d2[l] += d2[k]; d2[r] += d2[k];
}
else {
if(mx1[l] < mx1[r]) swap(l, r);
mx1[l] += d1[k];
mx1[r] += d2[k]; mx2[l] += d2[k]; mx2[r] += d2[k];
sm[l] += d1[k] * len[l]; sm[l] += d2[k] * slen[l];
sm[r] += d2[k] * (len[r] + slen[r]);
d1[l] += d1[k];
d1[r] += d2[k]; d2[l] += d2[k]; d2[r] += d2[k];
}
d1[k] = d2[k] = 0;
}
void push_up(int k) {
sm[k] = sm[ls] + sm[rs];
if(mx1[ls] == mx1[rs]) {
mx1[k] = mx1[ls];
mx2[k] = max(mx2[ls], mx2[rs]);
len[k] = len[ls] + len[rs];
slen[k] = slen[ls] + slen[rs];
}
if(mx1[ls] > mx1[rs]) {
mx1[k] = mx1[ls];
mx2[k] = max(mx2[ls], mx1[rs]);
len[k] = len[ls];
slen[k] = slen[ls] + slen[rs] + len[rs];
}
if(mx1[ls] < mx1[rs]) {
mx1[k] = mx1[rs];
mx2[k] = max(mx1[ls], mx2[rs]);
len[k] = len[rs];
slen[k] = slen[ls] + slen[rs] + len[ls];
}
}
void build(int k, int l, int r) {
mx1[k] = mx2[k] = len[k] = slen[k] = d1[k] = d2[k] = sm[k] = 0;
if(l == r) return ;
build(ls, l, mid); build(rs, mid + 1, r);
}
void modify(int k, int l, int r, int x, int y) {
if(l == r) {
mx1[k] = sm[k] = y; len[k] = 1;
mx2[k] = slen[k] = d1[k] = d2[k] = 0;
return ;
}
push_down(k);
if(x <= mid) modify(ls, l, mid, x, y);
else modify(rs, mid + 1, r, x, y);
push_up(k);
}
void add(int k, int l, int r, int x, int y) {
if(l >= x && r <= y) {
mx1[k]++; mx2[k]++; d1[k]++; d2[k]++; sm[k] += (len[k] + slen[k]);
return ;
}
push_down(k);
if(x <= mid) add(ls, l, mid, x, y);
if(y >= mid + 1) add(rs, mid + 1, r, x, y);
push_up(k);
}
void qmin(int k, int l, int r, int x, int y, int p) {
if(l >= x && r <= y) {
debug("[%lld %lld] for %lld // %lld %lld\n", l, r, p, mx1[k], mx2[k]);
if(p >= mx1[k]) return ;
if(p <= mx2[k]) {
push_down(k);
qmin(ls, l, mid, x, y, p);
qmin(rs, mid + 1, r, x, y, p);
push_up(k);
return ;
}
debug("At [%lld %lld] (%lld) {%lld %lld %lld}\n", l, r, len[k], d1[k], sm[k], mx1[k]);
d1[k] -= mx1[k] - p;
sm[k] -= (mx1[k] - p) * len[k];
mx1[k] = p;
debug("{%lld %lld %lld}\n", d1[k], sm[k], mx1[k]);
return ;
}
push_down(k);
if(x <= mid) qmin(ls, l, mid, x, y, p);
if(y >= mid + 1) qmin(rs, mid + 1, r, x, y, p);
push_up(k);
}
}Seg;
struct Binay_tree {
int cnt[N];
void clear() { memset(cnt, 0, sizeof(cnt));
}
void add(int x) {
while(x < N) cnt[x]++, x += x & -x;
}
int qry(int x) {
int ans = 0;
while(x) ans += cnt[x], x -= x & -x;
return ans;
}
}Bin;
void main(int *a, int *A) {
Seg.build(1, 1, n); Bin.clear();
for(i = 1; i <= n; ++i) mp[a[i]] = i;
for(i = 1; i <= n; ++i) {
int p = mp[i]; Bin.add(p); k = Bin.qry(p);
// if(i == 4) {
// if(p != n) Seg.add(1, 1, n, p + 1, n);
// Seg.modify(1, 1, n, p, i + 1);
// if(p != 1) Seg.qmin(1, 1, n, 1, p - 1, k);
//
// }
// else {
if(p != n) Seg.add(1, 1, n, p + 1, n);
Seg.modify(1, 1, n, p, i + 1);
if(p != 1) Seg.qmin(1, 1, n, 1, p - 1, k);
// }
A[i] = Seg.sm[1];
// printf(">>> %lld : %lld\n", i, A[i]);
}
}
}
int a[N], A[N], B[N];
signed main()
{
freopen("scar.in", "r", stdin);
freopen("scar.out", "w", stdout);
// srand(time(NULL));
// T=read();
// while(T--) {
//
// }
n = read();
for(i = 1; i <= n; ++i) a[i] = read();
Sol :: main(a, A);
// for(i = 1; i <= n; ++i) debug("%lld ", A[i]); debug("\n");
reverse(a + 1, a + n + 1);
Sol :: main(a, B);
for(i = 1; i <= n; ++i) printf("%lld\n", A[i] + B[i] - i * (i + 2));
return 0;
}