#include <bits/stdc++.h>
using namespace std;
// We will compress all coordinates (store locations, query locations,
// plus sentinel -2e8 and +2e8). Then build a segment tree on [0..m-1].
//
// Each update is for an interval (prv, nxt) belonging to some store type.
// The code "places" that interval in exactly one leaf, determined by
// comparing (prv + nxt)/2 to the node's 'midCoord'. At the leaf, we insert
// (prv, nxt) into two multisets: one tracking all "prv"s, and one tracking
// all "nxt"s. Then minv = smallest prv in that leaf, maxv = largest nxt.
//
// For queries, we do the same approach as original:
// answer = max( l - queryMin(l, +∞),
// queryMax(-∞, l) - l )
// If not all k store types are open, answer = -1.
//
// This replicates the "bumbaclot" logic but uses an array-based segtree
// with coordinate compression.
static const long long NEG_INF = -200000001; // slightly < -2e8
static const long long POS_INF = 200000001; // slightly > 2e8
// -----------------------------------------------------------
// Segment tree node
struct Node {
// index of children in seg[] array
int leftChild = 0, rightChild = 0;
// each internal node covers [start..end) in compressed indices
// we store a "midCoord" = (vals[start] + vals[end-1]) / 2
// used to decide whether an interval's midpoint belongs left or right
long long midCoord = 0;
// If leaf, we store a multiset of "prv" and a multiset of "nxt".
// Then minv = minimum of all prv in this leaf,
// maxv = maximum of all nxt in this leaf.
multiset<long long> mins;
multiset<long long> maxs;
// Aggregates from children:
long long minv = +LLONG_MAX;
long long maxv = -LLONG_MIN;
// We'll set isLeaf if (end - start) == 1
bool isLeaf = false;
};
// We'll have up to 4*m nodes if m is the number of distinct coordinates.
static const int MAXN = 800000;
Node seg[MAXN]; // The segment tree array
int segAlloc = 1; // root = 1
// We'll store the compressed coords in vals[].
vector<long long> vals;
// -----------------------------------------------------------
// Build the segment tree in array form
// idx = current node index in seg[]
// range [start..end) of the compressed array
void buildTree(int idx, int start, int end) {
if (end - start == 1) {
// Leaf
seg[idx].isLeaf = true;
seg[idx].leftChild = seg[idx].rightChild = 0;
seg[idx].mins.clear();
seg[idx].maxs.clear();
seg[idx].minv = LLONG_MAX;
seg[idx].maxv = -LLONG_MAX;
// midCoord not used in leaf
return;
}
seg[idx].isLeaf = false;
int mid = (start + end) >> 1;
seg[idx].leftChild = ++segAlloc;
buildTree(seg[idx].leftChild, start, mid);
seg[idx].rightChild = ++segAlloc;
buildTree(seg[idx].rightChild, mid, end);
// midCoord is the midpoint in the original coordinate space:
// (vals[start] + vals[end-1]) / 2
long long leftVal = vals[start], rightVal = vals[end - 1];
seg[idx].midCoord = (leftVal + rightVal) >> 1;
// minv, maxv aggregated from children
seg[idx].minv = min(seg[seg[idx].leftChild].minv,
seg[seg[idx].rightChild].minv);
seg[idx].maxv = max(seg[seg[idx].leftChild].maxv,
seg[seg[idx].rightChild].maxv);
}
// -----------------------------------------------------------
// Insert or erase an interval (prv, nxt) at node idx covering [start..end).
// We'll decide left or right by comparing midpoint = (prv + nxt)/2
// to seg[idx].midCoord.
//
// If it's a leaf, we insert/erase (prv,nxt) from that leaf's multisets.
void update(int idx, int start, int end,
long long prv, long long nxt, bool add)
{
if (seg[idx].isLeaf) {
// Insert or erase from the leaf
if (add) {
seg[idx].mins.insert(prv);
seg[idx].maxs.insert(nxt);
} else {
// guaranteed to exist, per problem logic
seg[idx].mins.erase(seg[idx].mins.find(prv));
seg[idx].maxs.erase(seg[idx].maxs.find(nxt));
}
// Recompute minv, maxv in this leaf
if (seg[idx].mins.empty()) {
seg[idx].minv = LLONG_MAX;
seg[idx].maxv = -LLONG_MAX;
} else {
seg[idx].minv = *seg[idx].mins.begin();
seg[idx].maxv = *seg[idx].maxs.rbegin();
}
return;
}
// Not a leaf => pick child
long long midVal = seg[idx].midCoord;
long long midPoint = (prv + nxt) >> 1; // integer division
if (midPoint <= midVal) {
// go left
update(seg[idx].leftChild, start, (start+end)/2, prv, nxt, add);
} else {
// go right
update(seg[idx].rightChild, (start+end)/2, end, prv, nxt, add);
}
// Recompute this node's minv, maxv from children
seg[idx].minv = min(seg[seg[idx].leftChild].minv,
seg[seg[idx].rightChild].minv);
seg[idx].maxv = max(seg[seg[idx].leftChild].maxv,
seg[seg[idx].rightChild].maxv);
}
// -----------------------------------------------------------
// Query the minimum "prv" in the subrange [L, R] of original coords
// We'll pass the node range in compressed indices [start..end).
// We'll skip nodes that do not intersect [L, R].
long long queryMin(int idx, int start, int end,
long long L, long long R)
{
// If [vals[start], vals[end-1]] is entirely disjoint from [L,R], skip
if (vals[end-1] < L || vals[start] > R) {
return LLONG_MAX;
}
// If [vals[start], vals[end-1]] is fully inside [L,R], take this node's minv
if (L <= vals[start] && vals[end-1] <= R) {
return seg[idx].minv;
}
// If leaf, partially overlapping => just return its minv
if (seg[idx].isLeaf) {
return seg[idx].minv;
}
// Otherwise, split
int mid = (start + end) >> 1;
long long leftAns = queryMin(seg[idx].leftChild, start, mid, L, R);
long long rightAns = queryMin(seg[idx].rightChild, mid, end, L, R);
return min(leftAns, rightAns);
}
// -----------------------------------------------------------
// Query the maximum "nxt" in the subrange [L, R] of original coords
long long queryMax(int idx, int start, int end,
long long L, long long R)
{
if (vals[end-1] < L || vals[start] > R) {
return -LLONG_MAX;
}
if (L <= vals[start] && vals[end-1] <= R) {
return seg[idx].maxv;
}
if (seg[idx].isLeaf) {
return seg[idx].maxv;
}
int mid = (start + end) >> 1;
long long leftAns = queryMax(seg[idx].leftChild, start, mid, L, R);
long long rightAns = queryMax(seg[idx].rightChild, mid, end, L, R);
return max(leftAns, rightAns);
}
// -----------------------------------------------------------
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k, q;
cin >> n >> k >> q;
// We'll collect all events: open(0), close(1), query(2).
// Also collect coordinates for compression: store locations, query locations.
vector<array<long long,4>> events;
events.reserve(n*2 + q);
vals.reserve(n*2 + q + 4);
// We also want sentinel -2e8, +2e8:
vals.push_back(NEG_INF);
vals.push_back(POS_INF);
// read store info
for (int i=0; i<n; i++){
long long x, t, a, b;
cin >> x >> t >> a >> b;
t--; // zero-based type
// open at time=a => event (a,0,x,t)
events.push_back({a, 0, x, t});
// close at time=b+1 => event (b+1,1,x,t)
events.push_back({b+1,1, x, t});
// for compression
vals.push_back(x);
}
vector<long long> ans(q, 0);
// read queries
for (int i=0; i<q; i++){
long long l, y;
cin >> l >> y;
// event => (y,2,l,i)
events.push_back({y,2,l,i});
vals.push_back(l);
}
// sort events by time, then by type
sort(events.begin(), events.end(),
[](auto &A, auto &B){
if (A[0] != B[0]) return A[0] < B[0];
return A[1] < B[1];
});
// coordinate compress
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
int m = (int)vals.size();
// build segment tree on [0..m)
buildTree(1, 0, m);
// track each type's open store locations in a balanced tree
vector< multiset<long long> > storeOfType(k);
vector<int> openCount(k, 0);
int countTypesWithOpen = 0;
// We also put sentinel MIN, MAX in each type's set from the start,
// so that intervals (MIN, MAX) exist. But initially we do NOT add
// that interval to the segment tree unless the type actually opens a store.
// The original code does: s[t] = {MIN, MAX}.
// Then the segment tree is updated with (MIN,MAX) once the type "exists."
for(int t=0; t<k; t++){
storeOfType[t].insert(NEG_INF);
storeOfType[t].insert(POS_INF);
}
// A small helper function to add or remove the interval (prv,nxt)
auto doUpdate = [&](long long prv, long long nxt, bool add){
update(1, 0, m, prv, nxt, add);
};
for (auto &e : events) {
long long time = e[0];
int etype = (int)e[1];
long long xOrL = e[2];
int tOrQ = (int)e[3];
if (etype == 0) {
// open store of type t
int t = tOrQ;
auto &S = storeOfType[t];
// find position of xOrL in that set
// neighbors => prv < x < nxt
auto it = S.lower_bound(xOrL);
// 'it' is the first element >= xOrL
long long nxt = *it;
long long prv = *prev(it);
// remove (prv, nxt)
doUpdate(prv, nxt, false);
// add (prv, xOrL) and (xOrL, nxt)
doUpdate(prv, xOrL, true);
doUpdate(xOrL, nxt, true);
S.insert(xOrL);
// if first real store for type t => openCount[t] was 0 => increment
if (openCount[t] == 0) {
countTypesWithOpen++;
}
openCount[t]++;
}
else if (etype == 1) {
// close store
int t = tOrQ;
auto &S = storeOfType[t];
// find xOrL in S
auto it = S.find(xOrL);
// neighbors => (prv, x), (x, nxt) exist, remove them, add (prv,nxt)
long long prv = *prev(it);
long long nxt = *next(it);
doUpdate(prv, xOrL, false);
doUpdate(xOrL, nxt, false);
doUpdate(prv, nxt, true);
S.erase(it);
openCount[t]--;
if (openCount[t] == 0) {
countTypesWithOpen--;
}
}
else {
// query
int qidx = tOrQ;
// check if all k types are open
if (countTypesWithOpen < k) {
ans[qidx] = -1;
} else {
long long l = xOrL;
// get min boundary in [l, +∞)
long long mn = queryMin(1, 0, m, l, POS_INF);
// get max boundary in [-∞, l]
long long mx = queryMax(1, 0, m, NEG_INF, l);
// answer = max( l - mn, mx - l )
long long res = max(l - mn, mx - l);
ans[qidx] = res;
}
}
}
// print answers
for (auto &val : ans) {
cout << val << "\n";
}
return 0;
}
Compilation message (stderr)
new_home.cpp:42:22: warning: integer overflow in expression of type 'long long int' results in '-9223372036854775808' [-Woverflow]
42 | long long maxv = -LLONG_MIN;
| ^
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |