Submission #1191654

#TimeUsernameProblemLanguageResultExecution timeMemory
1191654The_SamuraiMeasures (CEOI22_measures)C++20
100 / 100
653 ms36452 KiB
// I stand with PALESTINE




// #pragma GCC optimize("Ofast,O3")
// #pragma GCC target("avx,avx2")
#include "bits/stdc++.h"

using namespace std;
using ll = long long;
const ll inf = 1e18;

/*
v[0] - mid + d <= v[1] + mid
max(v[0] - mid + 2d, v[1] - mid + d) <= v[2] + mid
max(v[0] - mid + 3d, v[1] - mid + 2d, v[2] - mid + d) <= v[3] + mid

max(v[0] - mid + 3d, v[1] - mid + 2d, v[2] - mid + d) = 
= max(v[0] - mid, v[1] - mid - d, v[2] - mid - 2d) + 3d = 
= max(v[0], v[1] - d, v[2] - 2d) + 3d - mid

max(v[0], v[1] - d, v[2] - 2d) + 3d - mid <= v[3] + mid
max(v[0], v[1] - d, v[2] - 2d) + 3d - mid <= v[3] + mid
max(v[0], v[1] - d, v[2] - 2d) + 3d - v[3] <= 2 * mid
(max(v[0], v[1] - d, v[2] - 2d) + 3d - v[3]) / 2 <= mid
*/

void out(ll x) {
    cout << x / 2;
    if (x % 2) cout << ".5";
    cout << ' ';
}

struct lazy {
    struct node {
        ll val, lazy;

        void merge(const node &a, const node &b) {
            val = max(a.val, b.val);
            lazy = 0;
        }

        void impact(ll v) {
            val += v;
            lazy += v;
        }

        void propagate(node &a, node &b) {
            if (lazy != 0) {
                a.impact(lazy);
                b.impact(lazy);
                lazy = 0;
            }
        }
    };

    vector<node> tree;
    int size;
    node neutral_element;

    void init(int n) {
        size = 1;
        while (size < n) size *= 2;
        tree.resize(2 * size);
        
        for (int i = size; i < 2 * size; i++) tree[i].val = -inf, tree[i].lazy = 0;
        for (int i = size - 1; i > 0; i--) tree[i].merge(tree[i << 1], tree[i << 1 | 1]);
        neutral_element.val = -2 * inf, neutral_element.lazy = 0;
    }

    void upd(int l, int r, ll v, int x, int lx, int rx) {
        if (l >= rx or lx >= r) return;
        if (l <= lx and rx <= r) {
            tree[x].impact(v);
            return;
        }
        tree[x].propagate(tree[x << 1], tree[x << 1 | 1]);
        int mid = (lx + rx) >> 1;
        upd(l, r, v, x << 1, lx, mid);
        upd(l, r, v, x << 1 | 1, mid, rx);
        tree[x].merge(tree[x << 1], tree[x << 1 | 1]);
    }

    void upd(int l, int r, ll v) {
        if (l > r) return;
        upd(l, r + 1, v, 1, 0, size);
    }

    node get(int l, int r, int x, int lx, int rx) {
        if (l >= rx or lx >= r) return neutral_element;
        if (l <= lx and rx <= r) return tree[x];
        tree[x].propagate(tree[x << 1], tree[x << 1 | 1]);
        int mid = (lx + rx) >> 1;
        node ans;
        ans.merge(get(l, r, x << 1, lx, mid), get(l, r, x << 1 | 1, mid, rx));
        return ans;
    }

    ll get(int l, int r) {
        if (l > r) return -inf;
        return get(l, r + 1, 1, 0, size).val;
    }
};

struct fenwick {
    vector<int> tree;
    int n;

    void init(int len) {
        n = len;
        tree.assign(n + 1, 0);
    }

    void upd(int i, int v) {
        for (i++; i <= n; i += i & (-i)) tree[i] += v;
    }

    int get(int i) {
        int sum = 0;
        for (i++; i > 0; i -= i & (-i)) sum += tree[i];
        return sum;
    }
};

void solve() {
    int n, m; ll d;
    cin >> n >> m >> d;
    vector<ll> a(n), b(m);
    for (int i = 0; i < n; i++) cin >> a[i];
    for (int i = 0; i < m; i++) cin >> b[i];

    auto all = a;
    for (int i = 0; i < m; i++) all.emplace_back(b[i]);
    sort(all.begin(), all.end());
    map<ll, int> mp;
    for (ll x: all) mp[x] = lower_bound(all.begin(), all.end(), x) - all.begin();

    lazy sg; sg.init(n + m);
    lazy sg2; sg2.init(n + m); // sg2 - for max
    fenwick fw; fw.init(n + m);

    vector<ll> v = a;
    ll mx = -1e18, ans2 = 0;
    auto recalc = [&]() -> void {
        mx = -1e18, ans2 = 0;
        for (int i = 0; i < v.size(); i++) {
            ans2 = max(ans2, mx + i * d - v[i]);
            mx = max(mx, v[i] - i * d);
        }
    };
    recalc();

    ll ans = 0;
    for (int i = 0; i < n; i++) {
        int pos = mp[a[i]]++;
        // ans = max(ans, sg.get())
        sg.upd(pos, pos, -sg.get(pos, pos) + fw.get(pos) * d - a[i]);
        sg2.upd(pos, pos, -sg2.get(pos, pos) + a[i] - fw.get(pos) * d);
        sg.upd(pos + 1, n + m - 1, d);
        sg2.upd(pos + 1, n + m - 1, -d);
        fw.upd(pos, 1);

        ans = max(ans, sg2.get(0, pos - 1) + sg.get(pos, n + m - 1));
        ans = max(ans, sg2.get(0, pos) + sg.get(pos + 1, n + m - 1));
    }

    for (int i = 0; i < m; i++) {
        int pos = mp[b[i]]++;
        sg.upd(pos, pos, -sg.get(pos, pos) + fw.get(pos) * d - b[i]);
        sg.upd(pos + 1, n + m - 1, d);
        ll shit = -sg2.get(pos, pos);
        sg2.upd(pos, pos, shit + b[i] - fw.get(pos) * d);
        sg2.upd(pos + 1, n + m - 1, -d);
        fw.upd(pos, 1);

        ans = max(ans, sg2.get(0, pos - 1) + sg.get(pos, n + m - 1));
        ans = max(ans, sg2.get(0, pos) + sg.get(pos + 1, n + m - 1));
        // for (int j = 0; j < n + m - 1; j++) {
        //     ans = max(ans, sg2.get(0, j) + sg.get(j + 1, n + m - 1));
        // }
        // cout << '\t' << sg2.get(pos, pos) << ' ' << sg.get(pos, n + m - 1) << ' ' << b[i] << ' ' << pos << ' ' << shit << endl;

        // v.emplace_back(b[i]);
        // sort(v.begin(), v.end());
        // recalc();
        // cout << ans << ' ' << ans2 << endl;
        // assert(ans == ans2);

        out(ans);
    }
}

int main() {
    cin.tie(0)->sync_with_stdio(false);

    int queries = 1;
#ifdef sunnatov
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    cin >> queries;
#else
    // cin >> queries;
#endif

    for (int test_case = 1; test_case <= queries; test_case++) {
#ifdef sunnatov
        cout << "Test case: " << test_case << endl;
#endif
        solve();
        cout << '\n';
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...