Submission #1153721

#TimeUsernameProblemLanguageResultExecution timeMemory
1153721Zero_OP새 집 (APIO18_new_home)C++20
0 / 100
154 ms76956 KiB
#include <bits/stdc++.h>

using namespace std;

//loops (warning : long long)
#define FOR(i, l, r) for(int i = (l); i < (r); ++i)
#define ROF(i, r, l) for(int i = (r - 1); i >= l; --i)

//pairs, tuples
#define mp make_pair
#define mt make_tuple
#define ff first
#define ss second

//vectors
#define all(v) begin(v), end(v)
#define rall(v) rbegin(v), rend(v)
#define pb push_back
#define eb emplace_back
#define sum_of(v) accumulate(all(v), 0ll)
#define sz(v) (int)v.size()
#define compact(v) v.erase(unique(all(v)), end(v))

//binary search
#define lwb lower_bound
#define upb upper_bound

//other stuffs
#define dbg(x) "[" #x " = " << (x) << "]"
#define file(task) if(fopen(task".inp", "r")){ freopen(task".inp", "r", stdin); freopen(task".out", "w", stdout); }

template<typename T>
bool minimize(T& a, const T& b){
    if(a > b) return a = b, true;
    return false;
}

template<typename T>
bool maximize(T& a, const T& b){
    if(a < b) return a = b, true;
    return false;
}

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using db = double;
using pi = pair<int, int>;
using pl = pair<ll, ll>;

using vi = vector<int>;
using vb = vector<bool>;
using vl = vector<ll>;
using vpi = vector<pi>;
using vpl = vector<pl>;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

struct SegmentTreeStack{
    struct Node{
        multiset<int> S;
        Node() : S() {}

        void insert(int x){
//            if(mn.empty()) mn.pb(x), mx.pb(x);
//            else mn.pb(min(mn.back(), x)), mx.pb(max(mx.back(), x));
            S.insert(x);
        }

        void erase(int x){
            assert(!S.empty());
            S.erase(S.lower_bound(x));
        }

        int get_max_distance(int x){
            if(S.empty()) return 0;
            int cur = max(x - *S.begin(), *S.rbegin() - x);
            assert(cur >= 0);
            return cur;
        }

        int size(){ return sz(S); }
    };

    int n;
    vector<Node> st;
    SegmentTreeStack(int _n) : n(_n), st(n << 2) {
//        cout << dbg(n) << '\n';
    }

    void update_insert(int id, int l, int r, int u, int v, int val){
//        cout << id << ' ' << l << ' ' << r << ' ' << u << ' ' << v << ' ' << val << '\n';
        if(u <= l && r <= v){
            st[id].insert(val);
        } else{
            int mid = l + r >> 1;
            if(u <= mid) update_insert(id << 1, l, mid, u, v, val);
            if(mid <  v) update_insert(id << 1 | 1, mid + 1, r, u, v, val);
        }
    }

    void update_erase(int id, int l, int r, int u, int v, int val){
        if(u <= l && r <= v){
            st[id].erase(val);
        } else{
            int mid = l + r >> 1;
            if(u <= mid) update_erase(id << 1, l, mid, u, v, val);
            if(mid <  v) update_erase(id << 1 | 1, mid + 1, r, u, v, val);
        }
    }

    int query(int id, int l, int r, int pos, int val, int k){
        k -= st[id].size();
        if(l == r){
            assert(k >= 0);
            return (k > 0 ? -1 : st[id].get_max_distance(val));
        }

        int mid = l + r >> 1;
        int nxt = (pos <= mid ? query(id << 1, l, mid, pos, val, k) :
                                query(id << 1 | 1, mid + 1, r, pos, val, k));
        if(nxt == -1) return -1;
        return max(st[id].get_max_distance(val), nxt);
    }

    void update_insert(int l, int r, int val){
//        cout << "ST insert : " << dbg(l) << dbg(r) << dbg(val) << '\n';
        if(l <= r) update_insert(1, 1, n, l, r, val);
    }

    void update_erase(int l, int r, int val){
//        cout << "ST erase : " << dbg(l) << dbg(r) << dbg(val) << '\n';
        if(l <= r) update_erase(1, 1, n, l, r, val);
    }
};

const int bound = (int)1e8 + 1;

namespace Solver{
    SegmentTreeStack T(3e5);
    int K, n; vi points;
    vector<multiset<int>> online;

    void init(int _K, vi _points){
        K = _K;
        points = _points;
        n = sz(points) - 2;
        T.n = n;
        online.resize(K);
        FOR(i, 0, K) online[i].insert(0), online[i].insert(n+1);
    }

    void insert_candidate_range(int l, int r){
        //(l, r]
//        cout << "insert candidate : " << l << ' ' << r << '\n';
        int pos = upper_bound(all(points), (points[l] + points[r]) / 2) - points.begin() - 1;
//        cout << dbg(points[l]) << dbg(points[pos]) << dbg(points[r]) << '\n';
        T.update_insert(l+1, pos, (l == 0 ? points[r] : points[l]));
        T.update_insert(pos+1, r, (r == n+1 ? points[l] : points[r]));
    }

    void erase_candidate_range(int l, int r){
        //(l, r]
//        cout << "erase candidate : " << l << ' ' << r << '\n';
        int pos = upper_bound(all(points), (points[l] + points[r]) / 2) - points.begin() - 1;
//        cout << dbg(points[l]) << dbg(points[pos]) << dbg(points[r]) << '\n';
        T.update_erase(l+1, pos, (l == 0 ? points[r] : points[l]));
        T.update_erase(pos+1, r, (r == n+1 ? points[l] : points[r]));
    }

    void insert(int t, int x){
//        cout << t << ' ' << x << '\n';
        if(sz(online[t]) == 2){
//            cout << "First insertion : " << 1 << ' ' << x << ' ' << points[x] << '\n';
//            cout << "First insertion : " << x+1 << ' ' << n << ' ' << points[x] << '\n';
//            cout << dbg(1) << dbg(x) << dbg(points[x]) << '\n';
            insert_candidate_range(0, x);
            insert_candidate_range(x, n+1);
        } else{
            if(online[t].find(x) == online[t].end()){
                int L = *prev(online[t].lower_bound(x));
                int R = *online[t].upper_bound(x);

//                cout << dbg(L) << dbg(R) << dbg(x) << '\n';
                erase_candidate_range(L, R);
                insert_candidate_range(L, x);
                insert_candidate_range(x, R);
            }
        }

        online[t].insert(x);
    }

//    void erase(int t, int x){
//        online[t].erase(online[t].lower_bound(x));
//        if(sz(online[t]) == 2){
//            T.update(1, x, -1);
//            T.update(x+1, n, -1);
//        } else{
//            if(online[t].find(x) == online[t].end()){
//                int L = *prev(online[t].lower_bound(x));
//                int R = *online[t].upper_bound(x);
//
//                erase_candidate_range(L, x);
//                erase_candidate_range(x, R);
//                insert_candidate_range(L, R);
//            }
//        }
//    }

    int query(int x){
//        cout << points[x] << dbg(x) << '\n';
        return T.query(1, 1, n, x, points[x], K);
    }
}

void testcase(int ntestcase){ //Subtask 3
    int N, K, Q;
    cin >> N >> K >> Q;

    vi points, x(N), t(N);
    FOR(i, 0, N){
        int a, b;
        cin >> x[i] >> t[i] >> a >> b;
        --t[i];
        points.pb(x[i]);
//        assert(a == 1 && b == (int)1e8);
    }

    vi l(Q), y(Q);
    FOR(i, 0, Q){
        cin >> l[i] >> y[i];
        points.pb(l[i]);
    }

    points.pb(0); points.pb(bound);
    sort(all(points)); compact(points);

    Solver::init(K, points);

    FOR(i, 0, N){
        x[i] = lower_bound(all(points), x[i]) - points.begin();
//        cout << dbg(t[i]) << dbg(x[i]) << '\n';
        Solver::insert(t[i], x[i]);
    }

    FOR(i, 0, Q){
        l[i] = lower_bound(all(points), l[i]) - points.begin();
        cout << Solver::query(l[i]) << '\n';
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);

    if(fopen("task.inp", "r")){
        freopen("task.inp", "r", stdin);
    }

    int T = 1;
    //cin >> T;
    FOR(i, 0, T) testcase(i);

    return 0;
}

Compilation message (stderr)

new_home.cpp: In function 'int main()':
new_home.cpp:257:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  257 |         freopen("task.inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...