結果
問題 | No.703 ゴミ拾い Easy |
ユーザー | tsutaj |
提出日時 | 2018-06-15 23:31:05 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 280 ms / 1,500 ms |
コード長 | 6,032 bytes |
コンパイル時間 | 1,066 ms |
コンパイル使用メモリ | 108,192 KB |
実行使用メモリ | 14,336 KB |
最終ジャッジ日時 | 2024-06-10 18:30:54 |
合計ジャッジ時間 | 8,499 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 3 ms
5,248 KB |
testcase_01 | AC | 3 ms
5,376 KB |
testcase_02 | AC | 3 ms
5,376 KB |
testcase_03 | AC | 3 ms
5,376 KB |
testcase_04 | AC | 3 ms
5,376 KB |
testcase_05 | AC | 3 ms
5,376 KB |
testcase_06 | AC | 3 ms
5,376 KB |
testcase_07 | AC | 3 ms
5,376 KB |
testcase_08 | AC | 3 ms
5,376 KB |
testcase_09 | AC | 3 ms
5,376 KB |
testcase_10 | AC | 3 ms
5,376 KB |
testcase_11 | AC | 3 ms
5,376 KB |
testcase_12 | AC | 3 ms
5,376 KB |
testcase_13 | AC | 3 ms
5,376 KB |
testcase_14 | AC | 4 ms
5,376 KB |
testcase_15 | AC | 4 ms
5,376 KB |
testcase_16 | AC | 4 ms
5,376 KB |
testcase_17 | AC | 3 ms
5,376 KB |
testcase_18 | AC | 4 ms
5,376 KB |
testcase_19 | AC | 4 ms
5,376 KB |
testcase_20 | AC | 4 ms
5,376 KB |
testcase_21 | AC | 4 ms
5,376 KB |
testcase_22 | AC | 5 ms
5,376 KB |
testcase_23 | AC | 4 ms
5,376 KB |
testcase_24 | AC | 273 ms
14,208 KB |
testcase_25 | AC | 271 ms
14,336 KB |
testcase_26 | AC | 271 ms
14,208 KB |
testcase_27 | AC | 270 ms
14,240 KB |
testcase_28 | AC | 274 ms
14,332 KB |
testcase_29 | AC | 268 ms
14,208 KB |
testcase_30 | AC | 274 ms
14,136 KB |
testcase_31 | AC | 266 ms
14,208 KB |
testcase_32 | AC | 268 ms
14,208 KB |
testcase_33 | AC | 268 ms
14,320 KB |
testcase_34 | AC | 212 ms
14,148 KB |
testcase_35 | AC | 214 ms
14,216 KB |
testcase_36 | AC | 220 ms
14,208 KB |
testcase_37 | AC | 212 ms
14,208 KB |
testcase_38 | AC | 220 ms
14,208 KB |
testcase_39 | AC | 213 ms
14,204 KB |
testcase_40 | AC | 216 ms
14,208 KB |
testcase_41 | AC | 214 ms
14,336 KB |
testcase_42 | AC | 220 ms
14,164 KB |
testcase_43 | AC | 217 ms
14,208 KB |
testcase_44 | AC | 3 ms
5,376 KB |
testcase_45 | AC | 3 ms
5,376 KB |
testcase_46 | AC | 280 ms
14,208 KB |
testcase_47 | AC | 268 ms
14,252 KB |
testcase_48 | AC | 4 ms
5,376 KB |
testcase_49 | AC | 4 ms
5,376 KB |
ソースコード
// 基本テンプレート #include <iostream> #include <iomanip> #include <cstdio> #include <string> #include <cstring> #include <deque> #include <list> #include <queue> #include <stack> #include <vector> #include <utility> #include <algorithm> #include <map> #include <set> #include <complex> #include <cmath> #include <limits> #include <cfloat> #include <climits> #include <ctime> #include <cassert> #include <numeric> #include <fstream> #include <functional> using namespace std; #define rep(i,a,n) for(int (i)=(a); (i)<(n); (i)++) #define repq(i,a,n) for(int (i)=(a); (i)<=(n); (i)++) #define repr(i,a,n) for(int (i)=(a); (i)>=(n); (i)--) #define debug(...) fprintf(stderr, __VA_ARGS__) #define int long long int template<typename T> void chmax(T &a, T b) {a = max(a, b);} template<typename T> void chmin(T &a, T b) {a = min(a, b);} template<typename T> void chadd(T &a, T b) {a = a + b;} typedef pair<int, int> pii; typedef long long ll; int dx[] = {0, 0, 1, -1}; int dy[] = {1, -1, 0, 0}; const ll INF = 1001001001001001LL; const ll MOD = 1000000007LL; // Convex Hull Trick (Verified: COLOCON 2018 Final C) // ・直線集合に直線を追加する // ・直線集合に含まれている関数の中で、 f(x) の最大値を求める // 直線を表現する型と、取得クエリの単位元 (最大値を返すので、大きい負の値とか) template<typename Type, const Type id> struct ConvexHullTrick { private: using Response = pair<Type, int>; struct Line { Type a, b; Line (Type a_ = 0, Type b_ = 0) : a(a_), b(b_) {} Type get(Type x) { return a*x + b; } }; struct Node { Line line; Node *lhs, *rhs; int index; Node(Line line_, int index_=-1) : line(line_), lhs(nullptr), rhs(nullptr), index(index_) {} ~Node() { if(lhs) delete lhs; if(rhs) delete rhs; } }; int N; vector<Type> pos; Node *root; public: // x の取りうる値を sort かつ unique にしたもの ConvexHullTrick(const vector<Type> &pos_) : N(pos_.size()), pos(pos_), root(nullptr) {} ~ConvexHullTrick() { if(root) delete root; } // 直線 f(x) = a*x + b を追加する (オプション: インデックスの情報も保持したいならする) void insert(Type a, Type b, int idx=-1) { Line line(a, b); root = update(root, 0, N, line, idx); } // 直線集合 F において、f(x) の最大値を返す Type get_value(Type x) const { int t = lower_bound(pos.begin(), pos.end(), x) - pos.begin(); assert(t < N && pos[t] == x); return query(root, 0, N, t).first; } // 直線集合 F において、f(x) の最大値を実現する直線のインデックスを返す // (複数ある場合はインデックスが最も小さいものを返す) int get_index(Type x) const { int t = lower_bound(pos.begin(), pos.end(), x) - pos.begin(); assert(t < N && pos[t] == x); return query(root, 0, N, t).second; } private: // クエリで処理する区間は閉区間なので注意!!! Node* update(Node* p, int lb, int ub, Line& l, int idx=-1) { if(!p) return new Node(l, idx); if(p -> line.get(pos[lb ]) >= l.get(pos[lb ]) && p -> line.get(pos[ub - 1]) >= l.get(pos[ub - 1])) { return p; } if(p -> line.get(pos[lb ]) <= l.get(pos[lb ]) && p -> line.get(pos[ub - 1]) <= l.get(pos[ub - 1])) { p -> line = l; p -> index = idx; return p; } int mid = (ub + lb) / 2; if(p -> line.get(pos[mid]) < l.get(pos[mid])) { swap(p -> line, l); swap(p -> index, idx); } if(p -> line.get(pos[lb]) <= l.get(pos[lb])) { p -> lhs = update(p -> lhs, lb, mid, l, idx); } else { p -> rhs = update(p -> rhs, mid, ub, l, idx); } return p; } Response comp(Response lhs, Response rhs) const { if(lhs.first != rhs.first) { return lhs.first > rhs.first ? lhs : rhs; } else { return lhs.second < rhs.second ? lhs : rhs; } } Response query(Node *p, int lb, int ub, int t) const { if(!p) return make_pair(id, -1); if(ub - lb == 1) return make_pair(p -> line.get(pos[t]), p -> index); int mid = (ub + lb) / 2; Response cur = make_pair(p -> line.get(pos[t]), p -> index); if(t < mid) { return comp(cur, query(p -> lhs, lb, mid, t)); } else { return comp(cur, query(p -> rhs, mid, ub, t)); } } }; /* // 使用例 int main() { ll N; scanf("%lld", &N); vector<ll> points(N); iota(points.begin(), points.end(), 1); vector<ll> X(N+1), Y(N+1); ConvexHullTrick<ll, LLONG_MIN> cht(points); for(ll j=1; j<=N; j++) { ll A; scanf("%lld", &A); ll x = 2*j, y = -(A + j*j); X[j] = -2*j; Y[j] = A + j*j; cht.insert(x, y, j); } for(auto p : points) { int idx = cht.get_index(p); printf("%lld\n", X[idx]*p + Y[idx] + p*p); } return 0; } */ const int S = 100010; signed main() { int N; cin >> N; vector<int> A(N+1), X(N+1), Y(N+1); for(int i=0; i<N; i++) cin >> A[i+1]; for(int i=0; i<N; i++) cin >> X[i+1]; for(int i=0; i<N; i++) cin >> Y[i+1]; vector<ll> points(S); iota(points.begin(), points.end(), 0); ConvexHullTrick<ll, LLONG_MIN> cht(points); vector<int> dp(N+1, INF); dp[0] = 0; for(int i=1; i<=N; i++) { if(i != 1) { int val = -cht.get_value(A[i]); dp[i] = val + A[i] * A[i]; } chmin(dp[i], dp[i-1] + (X[i] - A[i]) * (X[i] - A[i]) + Y[i] * Y[i]); int x = -2 * X[i], y = dp[i-1] + X[i]*X[i] + Y[i]*Y[i]; cht.insert(-x, -y); } cout << dp[N] << endl; return 0; }