제출 #529547

#제출 시각아이디문제언어결과실행 시간메모리
529547msg555Aliens (IOI16_aliens)C++14
60 / 100
2062 ms6740 KiB
#include "aliens.h" #include <vector> #include <algorithm> #include <iostream> #include <set> #include <cassert> using namespace std; long long squared(int x) { return 1ll * x * x; } template<typename T> struct line_elem { T a; T b; T x_start; bool point_query; line_elem() : a(0), b(0), x_start(0), point_query(false) {} line_elem(T x) : a(0), b(0), x_start(x), point_query(true) {} line_elem(T a, T b, T x_start = 0) : a(a), b(b), x_start(x_start), point_query(false) {} T get(T x) const { return a * x + b; } bool operator<(const line_elem& rhs) const { if (point_query || rhs.point_query) { return x_start < rhs.x_start; } return make_pair(a, b) < make_pair(rhs.a, rhs.b); } }; template<typename T> T cross_x(const line_elem<T>& X, const line_elem<T>& Y) { /* Returns the first x >= to when the lines intersect */ T da = X.a - Y.a; T db = Y.b - X.b; assert(da != 0); if (da < 0) { da = -da; db = -db; } if (db < 0) { return db / da; } return (db + da - 1) / da; } template<typename T> struct line_hull { /* Implements a max hull, get the max ax+b for all inserted lines. */ bool insert(T a, T b) { /* Insert line ax+b */ auto ln = line_elem<T>(a, b); auto it = st.lower_bound(ln); bool is_last = it == st.end(); if (!is_last && ln.a == it->a) { return false; } auto jt = it; bool is_first = it == st.begin(); if (!is_first) { --it; if (it->a == ln.a) { if (it == st.begin()) { is_first = true; } else { --it; } } } T lft_x = is_first ? numeric_limits<T>::min() : cross_x(*it, ln); T rht_x = is_last ? numeric_limits<T>::max() : cross_x(ln, *jt); if (rht_x <= lft_x) { return false; } if (!is_first) { while (it != st.begin()) { auto kt = it--; T prev_lft_x = cross_x(*it, *kt); if (prev_lft_x < lft_x) { ++it; break; } lft_x = cross_x(*it, ln); } ++it; } if (!is_last) { while (true) { auto kt = jt++; if (jt == st.end()) { break; } T prev_rht_x = cross_x(*kt, *jt); if (rht_x < prev_rht_x) { break; } rht_x = cross_x(ln, *jt); } --jt; } if (!is_last) { const_cast<line_elem<T>&>(*jt).x_start = rht_x; // I'm sorry } ln.x_start = lft_x; if (it != jt) { const_cast<line_elem<T>&>(*it++) = ln; // I'm sorry if (it != jt) { st.erase(it, jt); } } else { st.insert(ln); } return true; } T get(T x) const { auto it = st.upper_bound(x); --it; return it->get(x); } set<line_elem<T> > st; }; const size_t MAXN = 100010; pair<int, int> A[MAXN]; long long ADJ[MAXN]; long long sample(int N, int K, long long C) { line_hull<long long> hl; long long val = 0; for (int i = 0; i <= N; i++) { val = 0; if (i) { long long x = A[i - 1].first; val = -hl.get(x) + squared(x) + C; } long long sadd = 1 + A[i].second - A[i].first; long long b = 2 * sadd; long long c = squared(sadd) + val - ADJ[i]; hl.insert(-b, -c); } return val - K * C; } long long take_photos(int N, int M, int K, vector<int> R, vector<int> C) { /* N = 100000; M = 100001; K = 50000; R.clear(); C.clear(); for (int i = 0; i < N; i++) { R.push_back(i); C.push_back(i + 1); } */ for (int i = 0; i < N; i++) { int ri = R[i]; int ci = C[i]; if (ri > ci) swap(ri, ci); A[i] = make_pair(ci, ci - ri); } sort(A, A + N); int j = 0; for (int i = 0; i < N; i++) { while (j > 0 && A[i].second >= A[j - 1].second + A[i].first - A[j - 1].first) { --j; } A[j++] = A[i]; } N = j; K = min(K, N); for (int i = 1; i < N; i++) { ADJ[i] = squared(max(0, 1 + A[i].second - A[i].first + A[i - 1].first)); } long long lo = 0; long long hi = 1 << 30; long long lstv = sample(N, K, hi); while (true) { long long v = sample(N, K, 2 * hi); if (v <= lstv) { hi *= 2; break; } lo = hi; hi *= 2; lstv = v; } while (lo + 3 <= hi) { long long md1 = lo + (hi - lo) / 3; long long md2 = lo + 2 * (hi - lo) / 3; if (sample(N, K, md1) < sample(N, K, md2)) { lo = md1 + 1; } else { hi = md2; } } long long result = numeric_limits<long long>::min(); for (long long i = lo; i < hi; i++) { result = max(result, sample(N, K, i)); } return result; }
#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...