Submission #219693

#TimeUsernameProblemLanguageResultExecution timeMemory
219693rama_pangBitaro, who Leaps through Time (JOI19_timeleap)C++14
100 / 100
744 ms42232 KiB
#include <bits/stdc++.h> using namespace std; class TimeLeap { // segment tree private: struct Node { bool collision; int st, et; // interval where if we start in the beginning of the segment in this time interval, we do not need to // timeleap at all until the collision long long timeleap; // the number of timeleaps needed to get from just the collision to the end of the segment. We // start at et if we collide with an L, or start at st if we collide with an R. Note that this // start points will be travelled through no matter what. int endtime; // endtime if there is a collision (since if there is, the endtime is forced) Node() {} Node(bool c, int s, int e, long long t, int et) : collision(c), st(s), et(e), timeleap(t), endtime(et) {} long long Travel(int &t) { // how many timeleaps are needed (note that t is modified to become the final time) long long res; if (!collision) { // we do not need to timeleap once we are in interval [st, et] if (t > et) { // travel back to et, then we do not need to timeleap again // (this is optimal since et is the last time where we do not need to timleap) res = t - et; t = et; } else { // we do not need to timeleap res = 0; t = max(t, st); } } else { // we collideR, so we first go to st/et from before collision then adding the rest of timeleaps res = max(t - st, 0) + timeleap; t = endtime; } return res; } friend Node merge(Node a, Node b) { Node res; if (!a.collision && !b.collision) { if (max(a.st, b.st) <= min(a.et, b.et)) { // no collision res = Node(false, max(a.st, b.st), min(a.et, b.et), 0, -1); } else if (a.et < b.st) { // there is a new collision with L res.collision = true; res.st = res.et = res.endtime = a.et; res.timeleap = b.Travel(res.endtime); } else if (a.st > b.et) { // there is a new collision with R res.collision = true; res.st = res.et = res.endtime = a.st; res.timeleap = b.Travel(res.endtime); } } else if (a.collision) { // we collide in a first, so we simply add b to the answer if we travel from a.endtime res = a; res.timeleap += b.Travel(res.endtime); } else if (b.collision) { // we collide in b first res = b; if (a.et < b.st) { res.st = res.et = res.endtime = a.et; res.timeleap = b.Travel(res.endtime); } else if (a.st > b.st) { res.st = res.et = res.endtime = a.st; res.timeleap = b.Travel(res.endtime); } } return res; } }; int sz; vector<Node> tree; void Update(int n, int tl, int tr, int pos, int newL, int newR) { if (tl == tr) return void(tree[n] = Node(false, newL, newR, 0, -1)); int mid = (tl + tr) / 2; int lc = n + 1; int rc = n + 2 * (mid - tl + 1); if (pos <= mid) { Update(lc, tl, mid, pos, newL, newR); } else { Update(rc, mid + 1, tr, pos, newL, newR); } tree[n] = merge(tree[lc], tree[rc]); } long long Query(int n, int tl, int tr, int l, int r, int &t) { if (tr < l || r < tl || tl > tr || l > r) return 0; if (l <= tl && tr <= r) return tree[n].Travel(t); int mid = (tl + tr) / 2; int lc = n + 1; int rc = n + 2 * (mid - tl + 1); long long res = 0; res += Query(lc, tl, mid, l, r, t); res += Query(rc, mid + 1, tr, l, r, t); return res; } public: TimeLeap(int n) : sz(n), tree(vector<Node>(2 * sz)) {} void Update(int pos, int newL, int newR) { return Update(1, 0, sz - 1, pos, newL, newR); } long long Query(int l, int r, int &t) { return Query(1, 0, sz - 1, l, r, t); } }; int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int N, Q; cin >> N >> Q; N--; TimeLeap Left(N), Right(N); auto Update = [&](int pos, int newL, int newR) { Left.Update(pos, newL - pos, newR - pos - 1); pos = N - pos - 1; Right.Update(pos, newL - pos, newR - pos - 1); return; }; auto Query = [&](int l, int r, int t1, int t2) { long long res = 0; if (l == r) { res = max(t1 - t2, 0); } else if (l < r) { t1 -= l, t2 -= r; res = Left.Query(l, --r, t1) + max(t1 - t2, 0); } else if (l > r) { l = N - l, r = N - r; t1 -= l, t2 -= r; res = Right.Query(l, --r, t1) + max(t1 - t2, 0); } return res; }; for (int i = 0; i < N; i++) { int L, R; cin >> L >> R; Update(i, L, R); } for (int i = 0; i < Q; i++) { int T; cin >> T; if (T == 1) { int P, S, E; cin >> P >> S >> E; Update(--P, S, E); } else if (T == 2) { int A, B, C, D; cin >> A >> B >> C >> D; cout << Query(--A, --C, B, D) << "\n"; } } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...