Submission #1370202

#TimeUsernameProblemLanguageResultExecution timeMemory
1370202magentorPyramid Base (IOI08_pyramid_base)C++20
100 / 100
4796 ms60660 KiB
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)
#define rep2(i, m ,n) for (int i = (m); i < (long long)(n); i++)
#define REP(i, n) for (long long i = 1; i < (long long)(n); i++)
typedef long long ll;
#define l(n) n.begin(),n.end()
#define YesNo(Q) Q==1?cout<<"Yes":cout<<"No"
struct S {
    int sum;
    int pre_min;
};

S e() {
    return {0, (int)(2e9)+2};
}

S op(S a, S b) {
    return {a.sum + b.sum, min(a.pre_min, a.sum + b.pre_min)};
}

template<class S, S(*e)(), S(*op)(S,S)>
struct segtree {
    int n;
    vector<S> node;

    segtree(vector<S> v) {
        n = 1;
        while (n < (int)v.size()) n *= 2;
        node.assign(2 * n, e());
        rep(i, (int)v.size()) node[n - 1 + i] = v[i];
        for (int i = n - 2; i >= 0; i--) {
            node[i] = op(node[2 * i + 1], node[2 * i + 2]);
        }
    }

    void set(int p, S x) {
        p += n - 1;
        node[p] = x;
        while (p > 0) {
            p = (p - 1) / 2;
            node[p] = op(node[2 * p + 1], node[2 * p + 2]);
        }
    }
    S get(int p) {
        return node[p + n - 1];
    }
    S sum(int a, int b, int k = 0, int l = 0, int r = -1) {
        if (r == -1) r = n;
        if (b <= l || r <= a) return e();
        if (a <= l && r <= b) return node[k];
        return op(sum(a, b, 2 * k + 1, l, (l + r) / 2),
                  sum(a, b, 2 * k + 2, (l + r) / 2, r));
    }
};

struct obb{
    int x1, y1, x2, y2;
    ll cost;
};

struct Event {
    int x;
    int y1, y2;
    ll cost;
    bool operator<(const Event& o) const {
        return x < o.x;
    }
};

bool check(int K, int M, int N, ll B, const vector<obb>& obs) {
    int max_x = M - K + 1;
    int max_y = N - K + 1;
    if (max_x < 1 || max_y < 1) return false;

    vector<Event> events;
    events.reserve(obs.size() * 2);
    
    for (const auto& ob : obs) {
        int lx = max(1, ob.x1 - K + 1);
        int rx = min(max_x, ob.x2);
        int ly = max(1, ob.y1 - K + 1);
        int ry = min(max_y, ob.y2);
        if (lx <= rx && ly <= ry) {
            events.push_back({lx, ly, ry, ob.cost});
            events.push_back({rx + 1, ly, ry, -ob.cost});
        }
    }

    sort(l(events));
    if (events.empty() || events[0].x > 1) return true;
    vector<S> init_v(max_y + 2, {0, 0});
    segtree<S, e, op> seg(init_v);
    vector<ll> D(max_y + 2, 0);

    int ev_idx = 0;
    int num_events = events.size();
    while (ev_idx < num_events) {
        int cur_x = events[ev_idx].x;
        if (cur_x > max_x) break;
        while (ev_idx < num_events && events[ev_idx].x == cur_x) {
            const auto& ev = events[ev_idx];
            D[ev.y1] += ev.cost;
            seg.set(ev.y1, {D[ev.y1], D[ev.y1]});
            
            D[ev.y2 + 1] -= ev.cost;
            seg.set(ev.y2 + 1, {D[ev.y2 + 1], D[ev.y2 + 1]});
            
            ev_idx++;
        }
        ll min_cost = seg.sum(1, max_y + 1).pre_min;
        if (min_cost <= B) return true;
    }
    return false;
}

int main(){
    int n,m,b,p;cin>>m>>n>>b>>p;
    vector<obb> obs(p);
    rep(i, p) {
        cin >> obs[i].x1 >> obs[i].y1 >> obs[i].x2 >> obs[i].y2 >> obs[i].cost;
    }

    int ok = 0;
    int ng = min(n, m) + 1;
    while (ng - ok > 1) {
        int mid = ok + (ng - ok) / 2;
        if (check(mid, m, n, b, obs)) {
            ok = mid;
        } else {
            ng = mid;
        }
    }

    cout << ok << endl;
    return 0;
}

Compilation message (stderr)

pyramid_base.cpp: In function 'bool check(int, int, int, ll, const std::vector<obb>&)':
pyramid_base.cpp:104:20: warning: narrowing conversion of 'D.std::vector<long long int>::operator[](((std::vector<long long int>::size_type)((int)ev.Event::y1)))' from '__gnu_cxx::__alloc_traits<std::allocator<long long int>, long long int>::value_type' {aka 'long long int'} to 'int' [-Wnarrowing]
  104 |             seg.set(ev.y1, {D[ev.y1], D[ev.y1]});
      |             ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pyramid_base.cpp:104:20: warning: narrowing conversion of 'D.std::vector<long long int>::operator[](((std::vector<long long int>::size_type)((int)ev.Event::y1)))' from '__gnu_cxx::__alloc_traits<std::allocator<long long int>, long long int>::value_type' {aka 'long long int'} to 'int' [-Wnarrowing]
pyramid_base.cpp:107:20: warning: narrowing conversion of 'D.std::vector<long long int>::operator[](((std::vector<long long int>::size_type)(((int)ev.Event::y2) + 1)))' from '__gnu_cxx::__alloc_traits<std::allocator<long long int>, long long int>::value_type' {aka 'long long int'} to 'int' [-Wnarrowing]
  107 |             seg.set(ev.y2 + 1, {D[ev.y2 + 1], D[ev.y2 + 1]});
      |             ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pyramid_base.cpp:107:20: warning: narrowing conversion of 'D.std::vector<long long int>::operator[](((std::vector<long long int>::size_type)(((int)ev.Event::y2) + 1)))' from '__gnu_cxx::__alloc_traits<std::allocator<long long int>, long long int>::value_type' {aka 'long long int'} to 'int' [-Wnarrowing]
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...