結果

問題 No.704 ゴミ拾い Medium
ユーザー tsutajtsutaj
提出日時 2018-06-15 23:55:00
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 360 ms / 1,500 ms
コード長 3,894 bytes
コンパイル時間 935 ms
コンパイル使用メモリ 104,204 KB
実行使用メモリ 29,112 KB
最終ジャッジ日時 2023-09-13 05:30:16
合計ジャッジ時間 11,062 ms
ジャッジサーバーID
(参考情報)
judge12 / judge13
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 7 ms
19,780 KB
testcase_01 AC 7 ms
19,788 KB
testcase_02 AC 7 ms
19,812 KB
testcase_03 AC 7 ms
19,716 KB
testcase_04 AC 7 ms
19,744 KB
testcase_05 AC 6 ms
19,732 KB
testcase_06 AC 7 ms
19,776 KB
testcase_07 AC 6 ms
19,988 KB
testcase_08 AC 7 ms
19,804 KB
testcase_09 AC 7 ms
19,840 KB
testcase_10 AC 7 ms
19,748 KB
testcase_11 AC 7 ms
19,712 KB
testcase_12 AC 7 ms
19,812 KB
testcase_13 AC 7 ms
19,860 KB
testcase_14 AC 8 ms
19,820 KB
testcase_15 AC 8 ms
19,844 KB
testcase_16 AC 8 ms
19,740 KB
testcase_17 AC 8 ms
19,748 KB
testcase_18 AC 8 ms
19,752 KB
testcase_19 AC 8 ms
19,732 KB
testcase_20 AC 8 ms
19,892 KB
testcase_21 AC 8 ms
19,816 KB
testcase_22 AC 8 ms
20,000 KB
testcase_23 AC 8 ms
19,732 KB
testcase_24 AC 356 ms
28,764 KB
testcase_25 AC 358 ms
28,692 KB
testcase_26 AC 355 ms
29,112 KB
testcase_27 AC 354 ms
28,696 KB
testcase_28 AC 360 ms
28,972 KB
testcase_29 AC 356 ms
28,860 KB
testcase_30 AC 356 ms
28,844 KB
testcase_31 AC 356 ms
28,668 KB
testcase_32 AC 355 ms
28,808 KB
testcase_33 AC 355 ms
28,648 KB
testcase_34 AC 302 ms
28,664 KB
testcase_35 AC 306 ms
28,780 KB
testcase_36 AC 302 ms
28,956 KB
testcase_37 AC 300 ms
28,940 KB
testcase_38 AC 301 ms
28,784 KB
testcase_39 AC 302 ms
28,844 KB
testcase_40 AC 302 ms
28,904 KB
testcase_41 AC 303 ms
28,752 KB
testcase_42 AC 302 ms
28,864 KB
testcase_43 AC 301 ms
28,812 KB
testcase_44 AC 7 ms
19,816 KB
testcase_45 AC 7 ms
19,796 KB
testcase_46 AC 355 ms
28,692 KB
testcase_47 AC 356 ms
28,668 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// 基本テンプレート
 
#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;

// Abstract Segment Tree (抽象・汎化セグメント木)
// Verified: AOJ DSL_2_A: Range Minimum Query (int型のみ)

const int SIZE = 1 << 19;
template<typename T>
struct segtree {
    // ノード、単位元
    T node[2*SIZE], I;

    // オペレーション (update, query の 2 つが必要?)
    T (*upd_f)(T, T), (*qry_f)(T, T);

    // 演算子と単位元をセットし、全ての node を単位元で初期化
    segtree(T (*op1)(T, T), T (*op2)(T, T), T X) {
        upd_f = op1;
        qry_f = op2;
        I = X;
        fill(node, node+2*SIZE, I);
    }

    // 配列 vec の値で初期化
    void init(vector<T> vec) {
        int N = (int)vec.size();
        for(int i=0; i<N; i++) {
            node[SIZE-1+i] = vec[i];
        }
        for(int i=SIZE-2; i>=0; i--) {
            node[i] = qry_f(node[2*i+1], node[2*i+2]);
        }
    }

    // 場所 idx に値 val を反映 (upd_f を用いて update)
    void update(int idx, T val) {
        idx += SIZE - 1;
        node[idx] = upd_f(node[idx], val);
        while(idx > 0) {
            // 登るときは qry_f を使うことに注意!!!
            idx = (idx - 1) / 2;
            node[idx] = qry_f(node[2*idx+1], node[2*idx+2]);
        }
    }

    // 半開区間 [a, b) に対してクエリを投げる
    // (qry_f を用いて処理)
    T query(int a, int b, int l=0, int r=SIZE, int k=0) {
        if(b <= l || r <= a) return I;
        if(a <= l && r <= b) return node[k];
        int mid = (l + r) / 2;
        T vl = query(a, b, l, mid, 2*k+1);
        T vr = query(a, b, mid, r, 2*k+2);
        return qry_f(vl, vr);
    }
};

// [[つかいかた]]
// update 用と query 用の関数と単位元 (関数を噛ませても結果が変わらないもの) を用意して宣言する
// 下の例だと、update 用の関数が upd で、query 用の関数が fnd で、単位元が INT_MAX

int upd(int a, int b) {return b;}
int fnd(int a, int b) {return min(a, b);}
segtree<int> seg_minus(upd, fnd, 1LL << 60);
segtree<int> seg_plus(upd, fnd, 1LL << 60);
 
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<int> dp(N+1, INF);
    dp[0] = 0;

    int it = 1;
    for(int i=1; i<=N; i++) {
        dp[i] = dp[i-1] + abs(A[i] - X[i]) + Y[i];
        chmin(dp[i], seg_minus.query(0, i) + A[i]);
        chmin(dp[i], seg_plus.query(0, i) - A[i]);
        seg_plus.update(i, dp[i-1] + Y[i] + X[i]);

        while(it <= i && X[it] < A[i+1]) {
            int val = dp[it-1] + Y[it] - X[it];
            seg_plus.update(it, INF);
            seg_minus.update(it, val);
            it++;
        }
    }
    cout << dp[N] << endl;
    return 0;
}
0