Submission #1074311

#TimeUsernameProblemLanguageResultExecution timeMemory
1074311joelgun14Growing Vegetables is Fun 5 (JOI24_vegetables5)C++17
30 / 100
5061 ms87040 KiB
// header file #include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> // pragma #pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") // macros // #define endl "\n" #define ll long long #define mp make_pair #define ins insert #define lb lower_bound #define pb push_back #define ub upper_bound #define lll __int128 #define fi first #define se second using namespace std; using namespace __gnu_pbds; typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_multiset; typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set; const int lim = 6e5 + 5; struct fenwick { int a[lim]; fenwick() { memset(a, 0, sizeof(a)); } void update(int idx, int val) { // cerr << idx << endl; assert(idx > 0); while(idx < lim) { a[idx] += val; idx += idx&-idx; } } void update(int l, int r, int val) { if(l > r) return; update(l, val); update(r + 1, -val); } int query(int idx) { if(idx >= lim) idx = lim - 1; int res = 0; while(idx) { res += a[idx]; idx -= idx&-idx; } return res; } }; int main() { ios_base::sync_with_stdio(0); cin.tie(NULL); int n; cin >> n; int a[2 * n + 5]; for(int i = 1; i <= 2 * n; ++i) cin >> a[i]; int b[n + 5], c[n + 5]; for(int i = 1; i <= n; ++i) cin >> b[i]; for(int i = 1; i <= n; ++i) cin >> c[i]; sort(b + 1, b + n + 1); sort(c + 1, c + n + 1); int l = 0, r = 1e9, res = -1; vector<pair<int, int>> v; for(int i = 1; i <= 2 * n; ++i) v.pb(mp(a[i], i)); sort(v.begin(), v.end()); fenwick cur; while(l <= r) { memset(cur.a, 0, sizeof(cur.a)); int mid = (l + r) >> 1; // max diff -> mid // try each partition what is the max diff // nanti ada banyak validity test, tinggal cek validity testnya mana aja pair<int, int> validb[2 * n + 5], validr[2 * n + 5]; for(int i = 1; i <= 2 * n; ++i) { // idx of element >= a[i] - mid validb[i].fi = lower_bound(b + 1, b + n + 1, a[i] - mid) - b; // idx of element <= a[i] + mid validb[i].se = upper_bound(b + 1, b + n + 1, a[i] + mid) - b - 1; // idx of element >= a[i] - mid validr[i].fi = lower_bound(c + 1, c + n + 1, a[i] - mid) - c; // idx of element <= a[i] + mid validr[i].se = upper_bound(c + 1, c + n + 1, a[i] + mid) - c - 1; // if(mid == 1) { // cerr << a[i] + mid << " " << upper_bound(c + 1, c + n + 1, a[i] + mid) - c - 1 << " " << validr[i].se << endl; // } } set<int> blue, red; for(int i = 1; i <= 2 * n; ++i) blue.ins(i), red.ins(i); for(auto p : v) { // process // cerr << "UPDATE" << endl; cur.update(max(1, p.se - n + 1), p.se, 1); // observe that blue on left/right of that segment can be invalid auto it = blue.begin(); int idx = p.se; // cerr << "TEST" << endl; while(blue.size() && (it = blue.lb(p.se - n + 1)) != blue.end() && *it <= p.se) { int tmp2 = cur.query(*it); if(tmp2 < validb[idx].fi || tmp2 > validb[idx].se) blue.erase(it); else break; } while(blue.size() && (it = blue.ub(p.se)) != blue.begin() && *--it >= p.se - n + 1) { int tmp2 = cur.query(*it); if(tmp2 < validb[idx].fi || tmp2 > validb[idx].se) blue.erase(it); else break; } if(p.se <= n) { cur.update(p.se + n + 1, 2 * n, 1); // observe that blue on left/right of that segment can be invalid while(blue.size() && (it = blue.lb(p.se + n + 1)) != blue.end() && *it <= p.se + 2 * n) { int tmp2 = cur.query(*it); if(tmp2 < validb[idx].fi || tmp2 > validb[idx].se) blue.erase(it); else break; } while(blue.size() && (it = blue.ub(p.se + 2 * n)) != blue.begin() && *--it >= p.se + n + 1) { int tmp2 = cur.query(*it); if(tmp2 < validb[idx].fi || tmp2 > validb[idx].se) blue.erase(it); else break; } } // cerr << "TEST" << endl; while(red.size() && (it = red.lb(p.se - n + 1)) != red.end() && *it <= p.se) { // cerr << "check " << *it << " due to " << p.se << " " << cur.query(*it) << " " << validr[idx].fi << endl; int tmp2 = cur.query(*it); if(tmp2 < validr[idx].fi || tmp2 > validr[idx].se) { // cerr << "delete1 " << *it << " due to " << p.se << endl; red.erase(it); } else break; } while(red.size() && (it = red.ub(p.se)) != red.begin() && *--it >= p.se - n + 1) { // cerr << "check " << *it << " due to " << p.se << " " << cur.query(*it) << " " << validr[idx].se << endl; int tmp2 = cur.query(*it); if(tmp2 < validr[idx].fi || tmp2 > validr[idx].se) { // cerr << "delete2 " << *it << " due to " << p.se << endl; red.erase(it); } else break; } if(p.se <= n) { // observe that red on left/right of that segment can be invalid while(red.size() && (it = red.lb(p.se + n + 1)) != red.end() && *it <= p.se + 2 * n) { // cerr << "check " << *it << " due to " << p.se << " " << cur.query(*it) << " " << validr[idx].fi << endl; int tmp2 = cur.query(*it); if(tmp2 < validr[idx].fi || tmp2 > validr[idx].se) { // cerr << "delete " << *it << " due to " << p.se << endl; red.erase(it); } else break; } while(red.size() && (it = red.ub(p.se + 2 * n)) != red.begin() && *--it >= p.se + n + 1) { // cerr << "check " << *it << " due to " << p.se << " " << cur.query(*it) << " " << validr[idx].se << endl; int tmp2 = cur.query(*it); if(tmp2 < validr[idx].fi || tmp2 > validr[idx].se) { // cerr << "delete " << *it << " due to " << p.se << endl; red.erase(it); } else break; } } } // blue and red have to complement each other bool ans = 0; for(auto x : blue) { if(red.count(x - n) || red.count(x + n)) ans = 1; } /* if(mid <= 20) { cerr << "DEBUG " << mid << endl; for(auto x : red) { cerr << x << " "; } cerr << endl; for(auto x : blue) { cerr << x << " "; } cerr << endl; } */ if(ans) r = mid - 1, res = mid; else l = mid + 1; } cout << res << endl; // choose a contiguous segment L to R such that we use one color // N^2 approach -> pair greedily (sorted) // int res = 1e9; // for(int i = 1; i + n <= 2 * n + 1; ++i) { // vector<int> blue, red; // for(int j = 1; j < i; ++j) { // blue.pb(a[j]); // } // for(int j = i; j < i + n; ++j) { // red.pb(a[j]); // } // for(int j = i + n; j <= 2 * n; ++j) { // blue.pb(a[j]); // } // sort(blue.begin(), blue.end()); // sort(red.begin(), red.end()); // int mx = 0; // for(int k = 1; k <= n; ++k) { // mx = max({mx, abs(blue[k - 1] - b[k]), abs(red[k - 1] - c[k])}); // } // res = min(res, mx); // mx = 0; // swap(red, blue); // for(int k = 1; k <= n; ++k) { // mx = max({mx, abs(blue[k - 1] - b[k]), abs(red[k - 1] - c[k])}); // } // res = min(res, mx); // } // cout << res << endl; return 0; }
#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...