제출 #1271833

#제출 시각아이디문제언어결과실행 시간메모리
1271833win1702Global Warming (CEOI18_glo)C++20
15 / 100
2096 ms14948 KiB
// solve_calibration_lis.cpp // Baseline implementation: computes pref and suf (LIS ending at i and starting at i). // Provides a brute-force (slow) solver for small n (n <= 2000) that tries every segment [L,R] // and picks best d by trying a set of candidate d's derived from relative comparisons. // Also includes scaffolding / comments where an O(n log n) editorial solution should be placed. // // Compile: g++ -O2 solve_calibration_lis.cpp -std=c++17 -o solve // Run: ./solve < input.txt #include <bits/stdc++.h> using namespace std; using ll = long long; const int INF32 = 1e9; int LIS_length(const vector<ll>& a) { vector<ll> tails; for (ll x : a) { auto it = lower_bound(tails.begin(), tails.end(), x); if (it == tails.end()) tails.push_back(x); else *it = x; } return (int)tails.size(); } // patience that also returns prefLen ending at each i (length of LIS that ends exactly at i) vector<int> LIS_pref_end(const vector<ll>& a) { int n = (int)a.size(); vector<ll> tails; vector<int> pref(n, 0); // we also need tails values if needed later for (int i = 0; i < n; ++i) { auto it = lower_bound(tails.begin(), tails.end(), a[i]); int pos = it - tails.begin(); if (it == tails.end()) tails.push_back(a[i]); else *it = a[i]; pref[i] = pos + 1; } return pref; } // LIS from right: lengths of LIS starting at i vector<int> LIS_suf_start(const vector<ll>& a) { int n = (int)a.size(); vector<ll> tails; vector<int> suf(n, 0); // To compute LIS starting at i we can traverse reversed and use -a[j] to flip order // but simpler: run on reversed with same comparator vector<ll> rev = a; reverse(rev.begin(), rev.end()); vector<int> pref_rev = LIS_pref_end(rev); for (int i = 0; i < n; ++i) { suf[i] = pref_rev[n - 1 - i]; } return suf; } // Bruteforce: try every segment [L,R], and for each segment, //// try candidate d values (generated from differences between elements inside and outside). // This is O(n^3) worst-case if implemented naively; we restrict to small n fallback. int bruteforce_solution(const vector<ll>& a, ll x) { int n = (int)a.size(); int best = LIS_length(a); // generate candidate d values for a given segment by considering aligning an inside element // just above some outside element or just below — heuristic but exhaustive for small n: for (int L = 0; L < n; ++L) { for (int R = L; R < n; ++R) { // set of candidate d's we will try for this segment unordered_set<ll> cand; cand.reserve(1024); cand.insert(0); // allow d = 0 (no change) // try d that place a[i]+d = a[j] +/- 1 or equal a[j] for (int i = L; i <= R; ++i) { for (int j = 0; j < n; ++j) if (j < L || j > R) { // we want a[i] + d to be <= a[j] or just > a[j], so try around differences ll d1 = a[j] - a[i]; ll d2 = a[j] - a[i] + 1; ll d3 = a[j] - a[i] - 1; if (abs(d1) <= x) cand.insert(d1); if (abs(d2) <= x) cand.insert(d2); if (abs(d3) <= x) cand.insert(d3); } // also try extremes +/- x cand.insert(-x); cand.insert(x); } // now try each candidate d vector<ll> b = a; for (ll d : cand) { if (d < -x || d > x) continue; for (int k = L; k <= R; ++k) b[k] = a[k] + d; int lis = LIS_length(b); if (lis > best) best = lis; // restore quickly (we'll overwrite later anyway) for (int k = L; k <= R; ++k) b[k] = a[k]; } } } return best; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; long long x; if (!(cin >> n >> x)) return 0; vector<ll> a(n); for (int i = 0; i < n; ++i) cin >> a[i]; // 1) baseline LIS (no calibration) int baseLIS = LIS_length(a); // 2) compute pref and suf arrays (helpful for optimized solution) vector<int> pref = LIS_pref_end(a); vector<int> suf = LIS_suf_start(a); int best = baseLIS; // quick improvement: try to extend using single element shifts (choose segment length 1) // For each i, try d in [-x, x] that might increase LIS by connecting pref and suf. // We'll try to pick d so that a[i]+d fits between some prefix tail and some suffix start. // Naive attempt: try d values that align a[i] with a[j] or a[j]+/-1 for j != i. // (This is a heuristic quick win) for (int i = 0; i < n; ++i) { // candidate d's unordered_set<ll> cand; cand.insert(0); cand.insert(-x); cand.insert(x); for (int j = 0; j < n; ++j) if (j != i) { ll d1 = a[j] - a[i]; ll d2 = a[j] - a[i] + 1; ll d3 = a[j] - a[i] - 1; if (abs(d1) <= x) cand.insert(d1); if (abs(d2) <= x) cand.insert(d2); if (abs(d3) <= x) cand.insert(d3); } vector<ll> b = a; for (ll d : cand) { if (d < -x || d > x) continue; b[i] = a[i] + d; int lis = LIS_length(b); best = max(best, lis); b[i] = a[i]; } } // If n is small, run brute force full search (guaranteed correct) if (n <= 2000) { int bf = bruteforce_solution(a, x); best = max(best, bf); cout << best << "\n"; return 0; } // For large n, we output the best we can with available heuristics + pref/suf baseline. // NOTE: This is not the full editorial O(n log n) implementation. // To finish the fully correct and fast solution: // - compute for each i the possible "position" interval [Lpos[i], Rpos[i]] in tails // when shifted by any d in [-x,x] (requires global tails / coordinate compression) // - then sweep over R, maintain a segment tree / fenwick that stores the best chain length // you can get inside the current [L,R] window mapping to increasing target positions // - combine prefix best upto L-1 and suffix best after R+1 // This is somewhat long and delicate to implement correctly; if you want, I will fetch the // canonical editorial and finish the O(n log n) version exactly. Say "ok tra web" and mình sẽ làm. // For now print our best-found value (baseline + heuristics) cout << best << "\n"; 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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...