Submission #499170

#TimeUsernameProblemLanguageResultExecution timeMemory
499170600MihneaGolf (JOI17_golf)C++17
0 / 100
21 ms25804 KiB
#include <bits/stdc++.h> using namespace std; #define y1 ynot1 typedef long long ll; typedef long double ld; struct Box { int xmin; int xmax; int ymin; int ymax; }; const int N = 100000 + 7; const int INF = (int) 1e9 + 7; int n; int x1; int y1; int x2; int y2; Box boxes[N]; void normalization() { map<int, int> mx, my; for (int i = 0; i <= n + 1; i++) { mx[boxes[i].xmin] = 0; mx[boxes[i].xmax] = 0; my[boxes[i].ymin] = 0; my[boxes[i].ymax] = 0; } int c = 0; for (auto &it : mx) { it.second = ++c; } c = 0; for (auto &it : my) { it.second = ++c; } for (int i = 0; i <= n + 1; i++) { boxes[i].xmin = mx[boxes[i].xmin]; boxes[i].xmax = mx[boxes[i].xmax]; boxes[i].ymin = my[boxes[i].ymin]; boxes[i].ymax = my[boxes[i].ymax]; } } struct Segment { int where; int low; int high; int e_low; int e_high; int dp; }; /** segment tree of lasts **/ struct Node { int mn; int mx; }; Node operator + (Node a, Node b) { return {min(a.mn, b.mn), max(a.mx, b.mx)}; } const Node non = {2 * N, 0}; Node segt1[8 * N]; Node lazy1[8 * N]; void push(int v, int tl, int tr) { if (lazy1[v].mn == non.mn && lazy1[v].mx == non.mx) { return; } segt1[v] = segt1[v] + lazy1[v]; if (tl < tr) { lazy1[2 * v] = lazy1[2 * v] + lazy1[v]; lazy1[2 * v + 1] = lazy1[2 * v + 1] + lazy1[v]; } lazy1[v] = non; } void updsegt1(int v, int tl, int tr, int l, int r, int x) { push(v, tl, tr); if (tr < l || r < tl) { return; } if (l <= tl && tr <= r) { lazy1[v] = lazy1[v] + Node{x, x}; push(v, tl, tr); return; } int tm = (tl + tr) / 2; updsegt1(2 * v, tl, tm, l, r, x); updsegt1(2 * v + 1, tm + 1, tr, l, r, x); segt1[v] = segt1[2 * v] + segt1[2 * v + 1]; } void updsegt1(int l, int r, int x) { if (l > r) { return; } assert(1 <= l && l <= r && r <= 2 * (n + 2)); updsegt1(1, 1, 2 * (n + 2), l, r, x); } Node getsegt1(int v, int tl, int tr, int l, int r) { push(v, tl, tr); if (tr < l || r < tl) { return non; } if (l <= tl && tr <= r) { return segt1[v]; } int tm = (tl + tr) / 2; return getsegt1(2 * v, tl, tm, l, r) + getsegt1(2 * v + 1, tm + 1, tr, l, r); } Node getsegt1(int l, int r) { return getsegt1(1, 1, 2 * (n + 2), l, r); } void clr() { for (int i = 0; i < 8 * N; i++) { segt1[i] = non; lazy1[i] = non; } } vector<vector<Segment>> segs; vector<Segment> xSegs; vector<Segment> ySegs; bool cmpextlowX(int i, int j) { return xSegs[i].low < xSegs[j].low; } bool cmpexthighX(int i, int j) { return xSegs[i].high > xSegs[j].high; } bool cmpextY(int i, int j) { return ySegs[i].where < ySegs[j].where; } bool cmp(int i, int j) { return xSegs[i].e_low < xSegs[j].e_low; } void calculateextensions() { for (int step = 1; step <= 2; step++) { /// calculate x segs for (int i = 0; i <= n + 1; i++) { xSegs.push_back({boxes[i].ymin, boxes[i].xmin, boxes[i].xmax, 0, 2 * N, -1}); xSegs.push_back({boxes[i].ymax, boxes[i].xmin, boxes[i].xmax, 0, 2 * N, -1}); } for (int i = 0; i <= n + 1; i++) { swap(boxes[i].xmin, boxes[i].ymin); swap(boxes[i].xmax, boxes[i].ymax); } swap(xSegs, ySegs); } assert((int) xSegs.size() == 2 * (n + 2)); assert((int) ySegs.size() == 2 * (n + 2)); for (int step = 1; step <= 2; step++) { /// compute the extensions { vector<int> ordx(2 * (n + 2)), ordy; iota(ordx.begin(), ordx.end(), 0); ordy = ordx; sort(ordx.begin(), ordx.end(), cmpextlowX); sort(ordy.begin(), ordy.end(), cmpextY); { clr(); int ptr = 0; for (int it = 0; it < 2 * (n + 2); it++) { int i = ordx[it]; while (ptr < 2 * (n + 2) && ySegs[ordy[ptr]].where < xSegs[i].low) { updsegt1(ySegs[ordy[ptr]].low + 1, ySegs[ordy[ptr]].high - 1, ySegs[ordy[ptr]].where); ptr++; } xSegs[i].e_low = getsegt1(xSegs[i].where, xSegs[i].where).mx; } } { reverse(ordx.begin(), ordx.end()); /// optimization, daca nu merge, incearca cmpexthighX reverse(ordy.begin(), ordy.end()); clr(); int ptr = 0; for (int it = 0; it < 2 * (n + 2); it++) { int i = ordx[it]; while (ptr < 2 * (n + 2) && ySegs[ordy[ptr]].where > xSegs[i].high) { updsegt1(ySegs[ordy[ptr]].low + 1, ySegs[ordy[ptr]].high - 1, ySegs[ordy[ptr]].where); ptr++; } xSegs[i].e_high = getsegt1(xSegs[i].where, xSegs[i].where).mn; } } } /// checker for (auto &it : xSegs) { assert(it.e_low <= it.low); assert(it.high <= it.e_high); } swap(xSegs, ySegs); } segs.push_back(xSegs); segs.push_back(ySegs); } queue<pair<int, int>> q; void addToQ(int type, int index, int value) { assert(0 <= type && type < 2); assert(0 <= index && index < (int) segs[type].size()); assert(segs[type][index].dp == -1); segs[type][index].dp = value; q.push({type, index}); } signed main() { ios::sync_with_stdio(0); cin.tie(0); // freopen ("input", "r", stdin); cin >> x1 >> y1 >> x2 >> y2; cin >> n; for (int i = 1; i <= n; i++) { cin >> boxes[i].xmin >> boxes[i].xmax >> boxes[i].ymin >> boxes[i].ymax; } boxes[0].xmin = boxes[0].xmax = x1; boxes[0].ymin = boxes[0].ymax = y1; boxes[n + 1].xmin = boxes[n + 1].xmax = x2; boxes[n + 1].ymin = boxes[n + 1].ymax = y2; normalization(); /// do it later calculateextensions(); if (n > 1000) { /// exit(0); /// I wanted to measure the first part of the algorithm } addToQ(0, 0, 1); addToQ(0, 1, 1); addToQ(1, 0, 1); addToQ(1, 1, 1); for (int type = 0; type < 2; type++) { xSegs = segs[type]; vector<int> inds(2 * (n + 2)); iota(inds.begin(), inds.end(), 0); /// assert((int) inds.size() == (int) xSegs.size()); // continue; sort(inds.begin(), inds.end(), cmp); map<int, int> last; for (auto &it : inds) { xSegs[it].where = -1; assert(last[xSegs[it].where] <= xSegs[it].e_high); last[xSegs[it].where] = xSegs[it].e_high; } } while (!q.empty()) { auto itQ = q.front(); q.pop(); int type = itQ.first; int index = itQ.second; int dp = segs[type][index].dp; assert(2 * (n + 2) == (int) segs[type ^ 1].size()); for (int j = 0; j < 2 * (n + 2); j++) { if (segs[type ^ 1][j].dp == -1 && segs[type ^ 1][j].e_low <= segs[type][index].where && segs[type][index].where <= segs[type ^ 1][j].e_high && segs[type][index].e_low <= segs[type ^ 1][j].where && segs[type ^ 1][j].where <= segs[type][index].e_high) { addToQ(type ^ 1, j, segs[type][index].dp + 1); } } } for (auto &v : segs) { for (auto &seg : v) { assert(seg.dp != -1); } } x2 = boxes[n + 1].xmin; y2 = boxes[n + 1].ymin; int sol = INF; swap(x2, y2); for (auto &v : segs) { for (auto &seg : v) { if (x2 == seg.where && seg.e_low <= y2 && y2 <= seg.e_high) { sol = min(sol, seg.dp); } } swap(x2, y2); } cout << sol << "\n"; return 0; }

Compilation message (stderr)

golf.cpp: In function 'int main()':
golf.cpp:315:9: warning: unused variable 'dp' [-Wunused-variable]
  315 |     int dp = segs[type][index].dp;
      |         ^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...