思路
线段树维护前缀和。
分别考虑当前数字在中位数左右两种情况。考虑x在中位数右边时把<=x的数变成1,>x的变成-1,要求最大奇异值就是求一段-1、1区间和最大,最大前缀和-最小前缀和即可。按照x的大小对线段树进行区间更新,x在中位数左边时同理。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define PI acos(-1.0)
#define F first
#define S second
#define endl '
'
#define lson rt << 1
#define rson rt << 1 | 1
#define lowbit(x) (x & (-x))
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _per(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
const int maxn = 2e5 + 7;
const int maxm = 26e3 + 7;
const LL mod = 998244353;
vector<int> v[maxn];
int a[maxn], ans[maxn];
int n, m;
struct node
{
int mn, mx, lz;
} tree[maxn << 2];
void push_up(int rt)
{
tree[rt].mx = max(tree[lson].mx, tree[rson].mx);
tree[rt].mn = min(tree[lson].mn, tree[rson].mn);
}
void push_down(int rt)
{
if (tree[rt].lz)
{
tree[lson].lz += tree[rt].lz;
tree[rson].lz += tree[rt].lz;
tree[lson].mn += tree[rt].lz;
tree[lson].mx += tree[rt].lz;
tree[rson].mn += tree[rt].lz;
tree[rson].mx += tree[rt].lz;
tree[rt].lz = 0;
}
}
void build(int rt, int l, int r, int val)
{
if (l == r)
{
tree[rt].mx = tree[rt].mn = val * l;
tree[rt].lz = 0;
return;
}
tree[rt].lz = 0;
int mid = (l + r) >> 1;
build(lson, l, mid, val);
build(rson, mid + 1, r, val);
push_up(rt);
}
void update_range(int rt, int l, int r, int L, int R, int add)
{
if (l <= L && r >= R)
{
tree[rt].lz += add;
tree[rt].mn += add;
tree[rt].mx += add;
return;
}
push_down(rt);
int mid = (L + R) / 2;
if (mid >= l)
update_range(lson, l, r, L, mid, add);
if (mid < r)
update_range(rson, l, r, mid + 1, R, add);
push_up(rt);
}
int query_max(int rt, int l, int r, int L, int R)
{
if (l <= L && R <= r)
return tree[rt].mx;
push_down(rt);
int mid = (L + R) >> 1;
int ans = -inf;
if (l <= mid)
ans = max(ans, query_max(lson, l, r, L, mid));
if (mid < r)
ans = max(ans, query_max(rson, l, r, mid + 1, R));
return ans;
}
int query_min(int rt, int l, int r, int L, int R)
{
if (l <= L && R <= r)
return tree[rt].mn;
push_down(rt);
int mid = (L + R) >> 1;
int ans = inf;
if (l <= mid)
ans = min(ans, query_min(lson, l, r, L, mid));
if (mid < r)
ans = min(ans, query_min(rson, l, r, mid + 1, R));
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
_rep(i, 1, n)
{
cin >> a[i];
v[a[i]].push_back(i);
}
build(1, 0, n, -1);
_rep(i, 1, n)
{
for (int u : v[i])
update_range(1, u, n, 0, n, 2);
for (int u : v[i])
{
int mx = query_max(1, u, n, 0, n);
int mn = query_min(1, 0, u - 1, 0, n);
ans[u] = max((mx - mn - 1) / 2, ans[u]);
}
}
build(1, 0, n, 1);
_rep(i, 1, n)
{
for (int u : v[i])
{
int mx = query_max(1, u, n, 0, n);
int mn = query_min(1, 0, u - 1, 0, n);
ans[u] = max((mx - mn) / 2, ans[u]);
}
for (int u : v[i])
update_range(1, u, n, 0, n, -2);
}
_rep(i, 1, n)
{
cout << ans[i] << " ";
}
}