제출 #251870

#제출 시각아이디문제언어결과실행 시간메모리
251870oolimry새 집 (APIO18_new_home)C++14
100 / 100
1924 ms78736 KiB
#include <bits/stdc++.h> #define all(x) x.begin(), x.end() #define X first #define T second using namespace std; typedef pair<int,int> ii; typedef map<ii, int>::iterator iter; const int MAXN = 300005; const int INF = 2e8; int n, K, Q, sz; struct store { int X, id, T; }; struct query { int X, id, T, ans; }; struct line { int start, xintercept, open, close; }; ///line exists in time frame [open, close). It begins from start, and travells rightward. vector<store> stores[MAXN]; vector<query> queries; struct segmenttree{ vector<int> tree; void init(){ tree.assign(2*sz,0); } void update(int l, int r, int v){ for(l += sz, r += sz;l < r;l >>= 1, r >>= 1){ if(l&1){ tree[l] = max(tree[l], v); l++; } if(r&1){ r--; tree[r] = max(tree[r], v); } } } int query(int i){ int res = 0; for(i += sz;i > 0;i >>= 1) res = max(res, tree[i]); return res; } }; map<ii, int> open; ///map<ii(location, index), time> void solve(){ vector<line> lines; ///for each type of store, find the lines which exist for(int type = 1;type <= K;type++){ open.clear(); open[ii(-2*INF,0)] = 0; open[ii(2*INF,0)] = 0; for(store S : stores[type]){ ii search = ii(S.X, S.id); iter cur = open.find(search); if(cur == open.end()){ ///S is going to be opened iter nxt = open.upper_bound(search); iter pre = prev(nxt); int nxtX = (nxt->first).X; int preX = (pre->first).X; lines.push_back({(nxtX + preX + 1)/2, nxtX, nxt->T, S.T}); ///line between nxt and pre broken when S is added nxt->second = S.T; ///see footnote open[search] = S.T; } else{ ///S is going to be closed iter nxt = next(cur); iter pre = prev(cur); int nxtX = (nxt->first).X; int curX = (cur->first).X; int preX = (pre->first).X; lines.push_back({(nxtX + curX + 1)/2, nxtX, nxt->T, S.T}); ///line between nxt and cur broken when S is removed lines.push_back({(curX + preX + 1)/2, curX, cur->T, S.T}); ///line between cur and pre broken when S is removed nxt->second = S.T; ///see footnote open.erase(cur); } } lines.push_back({0, 2*INF, open[ii(2*INF,0)], sz}); ///this is in case some type doesn't exist at all, open(ii(2*INF,)) will be the last time a store existed } segmenttree tree; tree.init(); ///segment tree built over time sort(all(lines), [&](line a, line b){ return a.start < b.start; }); int lineptr = 0; for(query &q : queries){ while(lineptr < (int)lines.size() && lines[lineptr].start <= q.X){ ///add all lines with start <= q.X line L = lines[lineptr]; tree.update(L.open, L.close, L.xintercept); lineptr++; } q.ans = max(q.ans, tree.query(q.T) - q.X); } } int main(){ ios_base::sync_with_stdio(false); cin.tie(0); cin >> n >> K >> Q; vector<int> times; for(int i = 1;i <= n;i++){ int X, type, A, B; cin >> X >> type >> A >> B; stores[type].push_back({X, i, A}); ///open stores[type].push_back({X, i, B+1}); ///close times.push_back(A); times.push_back(B+1); } sort(times.begin(), times.end()); times.erase(unique(all(times)), times.end()); ///discretize time sz = times.size(); for(int type = 1;type <= K;type++){ for(store &S : stores[type]){ S.T = lower_bound(all(times), S.T) - times.begin(); ///discretize time } sort(all(stores[type]), [&](store a, store b){ return a.T < b.T; ///increasing X tiebreak by id }); } queries.resize(Q); for(int i = 0;i < Q;i++){ cin >> queries[i].X >> queries[i].T; queries[i].T = upper_bound(all(times), queries[i].T) - times.begin() - 1; ///discretize time queries[i].id = i; queries[i].ans = 0; } sort(all(queries), [&](query a, query b){ return a.X < b.X; }); solve(); ///solve for gradient = -1 slopes ///reverse everything for(query &q : queries) q.X = INF - q.X; reverse(all(queries)); for(int type = 1;type <= K;type++){ for(store &S : stores[type]) S.X = INF - S.X; } solve(); ///solve for gradient = 1 slopes sort(all(queries), [&](query a, query b){ return a.id < b.id; }); for(query q : queries){ if(q.ans >= INF) cout << "-1\n"; else cout << q.ans << "\n"; } } ///footnote: it's kinda complicated... Basically by updating the right value, it's saying that any line which references the right range must start from the previous S->T ///It's hard to explain... oops
#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...