[CF1539F] Strange Array(线段树)

思路

线段树维护前缀和。

分别考虑当前数字在中位数左右两种情况。考虑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 '\n'
#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] << " ";
    }
}
posted @ 2021-08-18 20:46  kurum!  阅读(31)  评论(0编辑  收藏  举报