• [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 '
    '
    #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] << " ";
        }
    }
    
  • 相关阅读:
    在Swift中定义属于自己的运算符
    计算型属性 vs 懒加载
    swift- mutating
    什么是CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI?
    微信授权登录-微信公众号和PC端网站
    PHP实现购物车的思路和源码分析
    PHP实现图片的等比缩放和Logo水印功能示例
    PHP实现IP访问限制及提交次数的方法详解
    Laravel 队列发送邮件
    laravel 定时任务通过队列发送邮件
  • 原文地址:https://www.cnblogs.com/hfcdyp/p/15158747.html
Copyright © 2020-2023  润新知