Submission #384388

#TimeUsernameProblemLanguageResultExecution timeMemory
384388apostoldaniel854Constellation 3 (JOI20_constellation3)C++14
100 / 100
496 ms85856 KiB
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
#define dbg(x) cerr << #x << " " << x << "\n"

struct segment_tree {
    vector <pair <int, int>> seg;
    int n;
    void init (int n) {
        seg.resize (1 + 4 * n);
    }
    void build (int node, int lb, int rb, vector <int> &v) {
        if (lb == rb) {
            seg[node] = {v[lb], lb};
            return;
        }
        int mid = (lb + rb) / 2, left_node = node * 2, right_node = node * 2 + 1;
        build (left_node, lb, mid, v);
        build (right_node, mid + 1, rb, v);
        seg[node] = max (seg[left_node], seg[right_node]);
    }
    pair <int, int> query_max (int node, int lb, int rb, int ql, int qr) {
        if (ql <= lb && rb <= qr)
            return seg[node];
        int mid = (lb + rb) / 2, left_node = node * 2, right_node = node * 2 + 1;
        pair <int, int> ans = {0, 0};
        if (ql <= mid)
            ans = max (ans, query_max (left_node, lb, mid, ql, qr));
        if (qr > mid)
            ans = max (ans, query_max (right_node, mid + 1, rb, ql, qr));
        return ans;
    }
};
const ll INF = 1e18;
struct special_set {
    multiset <pair <int, ll>> stars;
    ll more = 0;
    void update (ll x) {
        more += x;
    }
    void add (pair <int, ll> x) {
        x.second -= more;
        auto it = stars.upper_bound (x);
        if (it == stars.begin ())
            stars.insert (x);
        else {
            it = prev (it);
            if (x.second < it->second)
                stars.insert (x);
        }
        it = stars.upper_bound (x);
        while (it != stars.end () && x.second <= it->second) {
            stars.erase (it);
            it = stars.upper_bound (x);
        }
    }
    ll query (int x) {
        auto it = prev (stars.lower_bound ({x + 1, -INF}));
        return it->second + more;
    }
    int size () {
        return (int) stars.size ();
    }
    void join (special_set other) {
        for (auto it : other.stars)
            add ({it.first, it.second + other.more});
    }


};
segment_tree buildings;
const int MAX_N = 2e5;
int n;
vector <pair <int, int>> events[1 + MAX_N];
void solve (int lb, int rb, special_set &sol) {
    if (lb > rb) return;
    if (lb == rb) {
        ll total = 0;
        for (auto event : events[lb])
            total += event.second;
        sol.add ({0, total});
        for (auto event : events[lb])
            sol.add ({event.first, total - event.second});
        return;
    }
    pair <int, int> ans = buildings.query_max (1, 1, n, lb, rb);
    int mid = ans.second;
    int pivot = ans.first;
    special_set L, R;
    if (mid == rb)
        mid--;
    solve (lb, mid, L);
    solve (mid + 1, rb, R);
    ll topL = R.query (pivot), topR = L.query (pivot);
    L.update (topL);
    R.update (topR);
    if (L.size () < R.size ())
        swap (L, R);
    L.join (R);
    swap (sol, L);
}

int main () {
    ios::sync_with_stdio (false);
    cin.tie (0); cout.tie (0);
    cin >> n;
    vector <int> v (n + 1);
    for (int i = 1; i <= n; i++)
        cin >> v[i];
    buildings.init (n);
    buildings.build (1, 1, n, v);
    int m;
    cin >> m;
    while (m--) {
        int x, y, c;
        cin >> x >> y >> c;
        events[x].push_back ({y, c});
    }
    special_set sol;
    solve (1, n, sol);
    cout << sol.query (n) << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...