Problem:
ほそながいところ
高橋君は苹果(りんご)ちゃんとニューヨークを観光することになりました。
高橋君は観光するところに特に希望はなかったのですが、苹果ちゃんの熱烈な誘いにより、以下の地図にあるような"ほそながいところ"を観光することに決まりました。
Google マップ - (C)2012 Google
この"ほそながいところ"はとても細長く、直線とみなすことができます。また、"ほそながいところ"には片方の端にスタート地点が、もう片方の端にゴール地点があり、スタート地点からゴール地点へ向けて何台かの観光用の馬車が走っています。この馬車は以下のようなルールに従って運行されています。
馬車は
n
台あり、すべての馬車はスタート地点から出発してゴール地点まで進みます。
以下のすべての場合において馬車の大きさは無視できます。
途中で速度を変更することが難しいため、すべての馬車は馬車はそれぞれ1kmあたりを
S
i
(
S
i
は1以上の整数)分の等速で進みます。
馬車には出発する順番が定められており、この順番を守らなければなりません。ただし、ゴール地点に到着する順番について特に決まりはありません。
複数の馬車はスタート地点を同時に発車することはできず、ある馬車が発車すれば次の馬車が発車するまでに1分以上間をあけなければなりません。
ゴール地点は十分に広いため、何台の馬車が同時に到着しても構いません。また、ゴール地点に到着した馬車はそこで止まり、ずっとゴール地点にいます。
"ほそながいところ"は大変細長いため馬車は基本的に同じ場所に2台並ぶことはできません。しかし、特別に"すこしひろいところ"が
m
箇所あり、そこでのみ2台まで並ぶことができ、ある馬車が別の馬車を追い抜くことが可能です。
また、先述した"ほそながいところ"と"すこしひろいところ"について、以下の制約を満たします。
スタート地点からゴール地点までは直線的に結ばれており、その距離は(
dist
)km(
dist
は1以上の整数)
m
箇所の"すこしひろいところ"はスタート地点からゴール地点までのどこかにあり、それらはいずれもスタート地点およびゴール地点とは重なりません。また、それぞれの"すこしひろいところ"はスタート地点からちょうど(
D
i
)km(
D
i
は1以上の整数)の地点にあります。
これを聞いた高橋君は、以上に述べた馬車運行のルールを守りつつ馬車の出発時刻を調整することにより、1台目の馬車が発車してからすべての馬車が到着するまでにかかる時間を小さくできることを見抜きました。

高橋君の出した結果を知るために、
馬車の台数
n
, それぞれの馬車の速度に関するパラメータ
S
i
,"ほそながいところ"上に存在する"すこしひろいところ"の総数
m
,それぞれの"すこしひろいところ"のスタート地点からの距離
D
i
が与えられるので、
1台目の馬車が発車してからすべての馬車が到着するまでにかかる時間の最小値を求めるプログラムを書くことがあなたの仕事です。


なお、苹果ちゃんは"ほそながいところ"での観光を存分に楽しみましたが、高橋君はこの観光の後には「ほそながかった…」としかつぶやかなかったそうです。
Input
入力形式は以下のようになっている。
dist
n
S
1
S
2
..
S
n
m
D
1
D
2
..
D
m
dist
はスタート地点からゴール地点までの距離(km)を表す
n
はスタート地点を発車する馬車の数を表す
S
i
は馬車の速度を表し、
i
番目に出発する馬車は1kmを
(S
i
)
分で進むことを表す。
m
は"すこしひろいところ"の総数を表す
D
i
はスタート地点からそれぞれの"すこしひろいところ"への距離(km)を表す。
Constraints
1≤dist≤100000000(10
8
)
1≤n≤5
0≤m≤5
1≤S
i
≤100
0<D
i
<dist
i≠j
ならば
D
i
≠D
j
入力に出現する数はすべて整数である。
i < j
ならば、
i
番目に出発する馬車は
j
番目の馬車より1分以上早く出発しなければならない
Output
1台目の馬車が発車してからすべての馬車が到着するまでにかかる時間の最小値を1行に出力せよ。単位は分である。
Sample Input 1
100
2
1
2
0
Output for the Sample Input 1
201
2台目は1台目が出発した1分後に出発する。
Sample Input 2
100
2
2
1
0
Output for the Sample Input 2
200
2台目は1台目が出発した100分後に出発し、ゴールで1台目に追いつく。
Sample Input 3
100
3
2
1
1
1
50
Output for the Sample Input 3
200
2台目は1台目が出発した50分後に出発し、50mのひろいところで1台目を抜く。
3台目は1台目が出発した100分後に出発し、ゴールで1台目に追いつく。
Sample Input 4
100
4
3
1
1
3
2
40
60
Output for the Sample Input 4
421

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

long long Answer = (1LL << 62);
long long Dist;
long long N, S[19];
long long M, D[19];
long long Memo[19];
long long NumOrder;
vector<pair<int, int>> Order[1009];

void InitDFS(int dep, vector<int> cur, vector<pair<int, int>> rec) {
	if (dep == N - 1) {
		Order[NumOrder] = rec;
		NumOrder += 1;
		return;
	}
	for (int i = 0; i < cur.size(); i++) {
		for (int j = 0; j < cur.size(); j++) {
			if (cur[i] == 0 || cur[j] == 1) continue;
			vector<int> nex = cur;
			vector<pair<int, int>> nexrec = rec;
			nex[j] = 1;
			nexrec.push_back(make_pair(i, j));
			InitDFS(dep + 1, nex, nexrec);
		}
	}
}

bool hantei(vector<long long> Start) {
	for (int i = 0; i < N - 1; i++) {
		if (Start[i] >= Start[i + 1]) return false;
	}
	vector<vector<int>> Count(M, vector<int>{});
	for (int i = 0; i < N; i++) {
		for (int j = i + 1; j < N; j++) {
			if (Start[j] - Start[i] >= Dist * (S[i] - S[j])) continue;
			if ((Start[j] - Start[i]) % (S[i] - S[j]) != 0) return false;
			long long place = (Start[j] - Start[i]) / (S[i] - S[j]);
			long long flag = -1;
			for (int k = 0; k < M; k++) {
				if (place == D[k]) flag = k;
			}
			if (flag == -1) return false;
			Count[flag].push_back(Start[i] + S[i] * place);
		}
	}
	for (int i = 0; i < M; i++) {
		for (int j = 0; j < Count[i].size(); j++) {
			for (int k = j + 1; k < Count[i].size(); k++) {
				if (Count[i][j] == Count[i][k]) return false;
			}
		}
	}
	return true;
}

void dfs(int dep, vector<long long> cur, vector<pair<int, int>> goal) {
	if (dep == goal.size()) {
		if (hantei(cur) == false) return;
		long long score = 0;
		for (int i = 0; i < N; i++) score = max(score, cur[i] + Dist * S[i]);
		Answer = min(Answer, score);
		return;
	}

	// Recursion
	int idx1 = goal[dep].first;
	int idx2 = goal[dep].second;
	for (int i = 0; i <= M; i++) {
		vector<long long> cur2 = cur;
		if (i != M && idx1 < idx2 && S[idx1] <= S[idx2]) continue;
		if (i != M && idx1 > idx2 && S[idx1] >= S[idx2]) continue;
		if (i != M && idx1 < idx2) cur2[idx2] = cur[idx1] + D[i] * (S[idx1] - S[idx2]);
		if (i != M && idx1 > idx2) cur2[idx2] = cur[idx1] - D[i] * (S[idx2] - S[idx1]);
		if (i == M && idx1 < idx2) cur2[idx2] = cur[idx1] + max(1LL, Dist * (S[idx1] - S[idx2]));
		if (i == M && idx1 > idx2) cur2[idx2] = cur[idx1] - max(1LL, Dist * (S[idx2] - S[idx1]));
		dfs(dep + 1, cur2, goal);
	}
}

int main() {
	// Step 1. Input
	cin >> Dist;
	cin >> N;
	for (int i = 0; i < N; i++) cin >> S[i];
	cin >> M;
	for (int i = 0; i < M; i++) cin >> D[i];
	sort(D, D + M);

	// Step 2. Init
	vector<int> InitVec = vector<int>(N, 0);
	InitVec[0] = 1;
	InitDFS(0, InitVec, vector<pair<int, int>>{});

	// Step 3. Brute Force
	for (int i = 0; i < NumOrder; i++) {
		dfs(0, vector<long long>(N, 0), Order[i]);
	}

	// Step 4. Output
	cout << Answer << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3480
final_rank: 5

code_snippet: #include <bits/stdc++.h>

// clang-format off
#define rep(i, s ,n) for(int i=s, i##_len=(n); i<i##_len; ++i)
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
using ll = long long;
// 2^60
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
using namespace std;
using Graph = vector<vector<int>>;
template <typename T> ostream &operator<<(ostream &s, vector<vector<vector<T>>> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << "[" << i << "]" << endl; s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<vector<T>> const &v) { for (int i = 0; i < int(v.size()); ++i ){ s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<T> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << v[i]; if (i != int(v.size()) - 1) { s << ",";}} s << endl; return s;}
// clang-format on

// ポテンシャル付きUnionFind
struct UnionFind {
    vector<int> par, siz;
    vector<ll> diff_weight;

    UnionFind(int n) : par(n, -1), siz(n, 1), diff_weight(n) {
    }

    // 根を求める
    int root(int x) {
        if (par[x] == -1) {
            return x;
        } else {
            int r = root(par[x]);
            diff_weight[x] += diff_weight[par[x]];
            return par[x] = r;
        }
    }

    // x と y が同じグループに属するかどうか (根が一致するかどうか)
    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    // weight(y) - weight(x) = w となるように merge する
    bool merge(int x, int y, ll w) {
        // x と y それぞれについて、 root との重み差分を補正
        w += weight(x);
        w -= weight(y);

        x = root(x), y = root(y);
        if (x == y)
            return false;
        if (siz[x] < siz[y]) {
            swap(x, y);
            w = -w;
        }
        par[y] = x;
        siz[x] += siz[y];
        diff_weight[y] = w;
        return true;
    }

    ll weight(int x) {
        root(x);
        return diff_weight[x];
    }

    ll diff(int x, int y) {
        return weight(y) - weight(x);
    }

    // グループを返却する
    vector<vector<int>> groups() {
        vector<vector<int>> g(par.size());
        for (int i = 0; i < par.size(); ++i) {
            g[root(i)].push_back(i);
        }
        auto result = std::remove_if(g.begin(), g.end(), [](auto &x) { return x.empty(); });
        g.erase(result, g.end());
        return g;
    }

    // x を含むグループのサイズ
    int size(int x) {
        return siz[root(x)];
    }
};

int main(void) {
    ll dist;
    int n;
    cin >> dist >> n;
    vector<int> S(n);
    rep(i, 0, n) {
        cin >> S[i];
    }
    int m;
    cin >> m;
    vector<ll> D(m);
    rep(i, 0, m) {
        cin >> D[i];
    }

    ll ans = 1e18;
    auto check = [&](vector<ll> &T) {
        /*
        cout << "-------" << endl;
        cout << T;
        cout << "-------" << endl;
        */

        UnionFind uf(n);
        int cur = -1;
        rep(i, 0, n) {
            rep(j, i + 1, n) {
                ++cur;
                if (T[cur] == -1)
                    continue;
                if (uf.issame(i, j)) {
                    if (uf.diff(i, j) != T[cur]) {
                        return;
                    }
                } else {
                    uf.merge(i, j, T[cur]);
                }
            }
        }

        vector<map<ll, int>> count(m);
        rep(i, 0, n) {
            rep(j, i + 1, n) {
                if (not uf.issame(i, j)) {
                    return;
                }
                ll diff = uf.diff(i, j);
                if (diff < 1) {
                    return;
                }
                ll ig = dist * S[i];
                ll jg = diff + dist * S[j];
                if (jg < ig) {
                    bool ok = false;

                    rep(k, 0, m) {
                        ll it = uf.diff(0, i) + D[k] * S[i];
                        ll jt = uf.diff(0, j) + D[k] * S[j];
                        if (jt == it) {
                            ok = true;
                            count[k][it] += 1;
                        }
                    }
                    if (not ok) {
                        return;
                    }
                }
            }
        }

        rep(i, 0, m) {
            for (auto [t, cnt] : count[i]) {
                if (cnt >= 3) {
                    return;
                }
            }
        }

        ll need = 0;
        rep(i, 0, n) {
            ll diff = uf.diff(0, i);
            chmax(need, diff + S[i] * dist);
        }

        chmin(ans, need);
    };

    auto rec = [&](auto &&f, int x, int y, vector<ll> &T) -> void {
        if (x == n - 1) {
            check(T);
            return;
        }

        int nx;
        int ny;

        if (y == n - 1) {
            nx = x + 1;
            ny = nx + 1;
        } else {
            nx = x;
            ny = y + 1;
        }

        rep(i, 0, m) {
            if (S[x] > S[y]) {
                ll diff = D[i] * (S[x] - S[y]);
                T.push_back(diff);
                f(f, nx, ny, T);
                T.pop_back();
            }
        }

        if (S[y] < S[x]) {
            ll diff = dist * (S[x] - S[y]);
            T.push_back(diff);
            f(f, nx, ny, T);
            T.pop_back();
        }

        T.push_back(1);
        f(f, nx, ny, T);
        T.pop_back();

        T.push_back(-1);
        f(f, nx, ny, T);
        T.pop_back();
    };
    vector<ll> t;
    rec(rec, 0, 1, t);
    cout << ans << endl;
}
accuracy: 1
time_ms: 80
memory_kb: 3456
final_rank: 10

code_snippet: #include <bits/stdc++.h>

// clang-format off
#define rep(i, s ,n) for(int i=s, i##_len=(n); i<i##_len; ++i)
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
using ll = long long;
// 2^60
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
using namespace std;
using Graph = vector<vector<int>>;
template <typename T> ostream &operator<<(ostream &s, vector<vector<vector<T>>> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << "[" << i << "]" << endl; s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<vector<T>> const &v) { for (int i = 0; i < int(v.size()); ++i ){ s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<T> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << v[i]; if (i != int(v.size()) - 1) { s << ",";}} s << endl; return s;}
// clang-format on

// ポテンシャル付きUnionFind
struct UnionFind {
    vector<int> par, siz;
    vector<int> diff_weight;

    UnionFind(int n) : par(n, -1), siz(n, 1), diff_weight(n) {
    }

    // 根を求める
    int root(int x) {
        if (par[x] == -1) {
            return x;
        } else {
            int r = root(par[x]);
            diff_weight[x] += diff_weight[par[x]];
            return par[x] = r;
        }
    }

    // x と y が同じグループに属するかどうか (根が一致するかどうか)
    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    // weight(y) - weight(x) = w となるように merge する
    bool merge(int x, int y, int w) {
        // x と y それぞれについて、 root との重み差分を補正
        w += weight(x);
        w -= weight(y);

        x = root(x), y = root(y);
        if (x == y)
            return false;
        if (siz[x] < siz[y]) {
            swap(x, y);
            w = -w;
        }
        par[y] = x;
        siz[x] += siz[y];
        diff_weight[y] = w;
        return true;
    }

    int weight(int x) {
        root(x);
        return diff_weight[x];
    }

    int diff(int x, int y) {
        return weight(y) - weight(x);
    }

    // グループを返却する
    vector<vector<int>> groups() {
        vector<vector<int>> g(par.size());
        for (int i = 0; i < par.size(); ++i) {
            g[root(i)].push_back(i);
        }
        auto result = std::remove_if(g.begin(), g.end(), [](auto &x) { return x.empty(); });
        g.erase(result, g.end());
        return g;
    }

    // x を含むグループのサイズ
    int size(int x) {
        return siz[root(x)];
    }
};

int main(void) {
    ll dist;
    int n;
    cin >> dist >> n;
    vector<int> S(n);
    rep(i, 0, n) {
        cin >> S[i];
    }
    int m;
    cin >> m;
    vector<ll> D(m);
    rep(i, 0, m) {
        cin >> D[i];
    }

    ll ans = 1e18;
    auto check = [&](vector<ll> &T) {
        /*
        cout << "-------" << endl;
        cout << T;
        cout << "-------" << endl;
        */

        UnionFind uf(n);
        int cur = -1;
        rep(i, 0, n) {
            rep(j, i + 1, n) {
                ++cur;
                if (T[cur] == -1)
                    continue;
                if (uf.issame(i, j)) {
                    if (uf.diff(i, j) != T[cur]) {
                        return;
                    }
                } else {
                    uf.merge(i, j, T[cur]);
                }
            }
        }

        vector<map<ll, int>> count(m);
        rep(i, 0, n) {
            rep(j, i + 1, n) {
                if (not uf.issame(i, j)) {
                    return;
                }
                ll diff = uf.diff(i, j);
                if (diff < 1) {
                    return;
                }
                ll ig = dist * S[i];
                ll jg = diff + dist * S[j];
                if (jg < ig) {
                    bool ok = false;

                    rep(k, 0, m) {
                        ll it = uf.diff(0, i) + D[k] * S[i];
                        ll jt = uf.diff(0, j) + D[k] * S[j];
                        if (jt == it) {
                            ok = true;
                            count[k][it] += 1;
                        }
                    }
                    if (not ok) {
                        return;
                    }
                }
            }
        }

        rep(i, 0, m) {
            for (auto [t, cnt] : count[i]) {
                if (cnt >= 3) {
                    return;
                }
            }
        }

        ll need = 0;
        rep(i, 0, n) {
            ll diff = uf.diff(0, i);
            chmax(need, diff + S[i] * dist);
        }

        chmin(ans, need);
    };

    auto rec = [&](auto &&f, int x, int y, vector<ll> &T) -> void {
        if (x == n - 1) {
            check(T);
            return;
        }

        int nx;
        int ny;

        if (y == n - 1) {
            nx = x + 1;
            ny = nx + 1;
        } else {
            nx = x;
            ny = y + 1;
        }

        rep(i, 0, m) {
            if (S[x] > S[y]) {
                ll diff = D[i] * (S[x] - S[y]);
                T.push_back(diff);
                f(f, nx, ny, T);
                T.pop_back();
            }
        }

        if (S[y] < S[x]) {
            ll diff = dist * (S[x] - S[y]);
            T.push_back(diff);
            f(f, nx, ny, T);
            T.pop_back();
        }

        T.push_back(1);
        f(f, nx, ny, T);
        T.pop_back();

        T.push_back(-1);
        f(f, nx, ny, T);
        T.pop_back();
    };
    vector<ll> t;
    rec(rec, 0, 1, t);
    cout << ans << endl;
}
accuracy: 0.5384615384615384
time_ms: 80
memory_kb: 3456
final_rank: 15

code_snippet: #include <bits/stdc++.h>

// clang-format off
#define rep(i, s ,n) for(int i=s, i##_len=(n); i<i##_len; ++i)
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
using ll = long long;
// 2^60
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
using namespace std;
using Graph = vector<vector<int>>;
template <typename T> ostream &operator<<(ostream &s, vector<vector<vector<T>>> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << "[" << i << "]" << endl; s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<vector<T>> const &v) { for (int i = 0; i < int(v.size()); ++i ){ s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<T> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << v[i]; if (i != int(v.size()) - 1) { s << ",";}} s << endl; return s;}
// clang-format on

template <class Abel>
struct UnionFind {
    vector<int> par;
    vector<int> rank;
    vector<Abel> diff_weight;

    UnionFind(int n = 1, Abel SUM_UNITY = 0) {
        init(n, SUM_UNITY);
    }

    void init(int n = 1, Abel SUM_UNITY = 0) {
        par.resize(n);
        rank.resize(n);
        diff_weight.resize(n);
        for (int i = 0; i < n; ++i)
            par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;
    }

    int root(int x) {
        if (par[x] == x) {
            return x;
        } else {
            int r = root(par[x]);
            diff_weight[x] += diff_weight[par[x]];
            return par[x] = r;
        }
    }

    Abel weight(int x) {
        root(x);
        return diff_weight[x];
    }

    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    bool merge(int x, int y, Abel w) {
        w += weight(x);
        w -= weight(y);
        x = root(x);
        y = root(y);
        if (x == y)
            return false;
        if (rank[x] < rank[y])
            swap(x, y), w = -w;
        if (rank[x] == rank[y])
            ++rank[x];
        par[y] = x;
        diff_weight[y] = w;
        return true;
    }

    Abel diff(int x, int y) {
        return weight(y) - weight(x);
    }
};

typedef pair<int, int> pint;

long long dist;
int n, m;
long long S[11], D[11];

const long long INF = 1LL << 60;
long long res = INF;  // 答えを更新していく

// 各馬車が「どこですれ違うか」
void check(vector<long long> diffs) {
    UnionFind<long long> uf(n);
    int iter = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            long long diff = diffs[iter++];
            if (diff == -1)
                continue;

            if (uf.issame(i, j)) {
                long long curdiff = uf.diff(i, j);
                if (diff != curdiff)
                    return;
            } else {
                uf.merge(i, j, diff);
            }
        }
    }

    // 暫定回を求める
    ll ans = 0;
    for (int i = 0; i < n; ++i) {
        chmax(ans, uf.diff(0, i) + S[i] * dist);
    }

    // 整合性を確認
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            if (!uf.issame(i, j))
                return;  // 繋がっていない箇所があったら明らかに最適でないので return
            if (uf.diff(i, j) < 1)
                return;  // j が i の 1分後よりも早く出ていたらダメ

            // 追い越している場合はどこで追い越してるか
            long long start_i = uf.diff(0, i);
            long long goal_i = start_i + S[i] * dist;
            long long start_j = uf.diff(0, j);
            long long goal_j = start_j + S[j] * dist;
            if (goal_j < goal_i) {
                int pl = -1;
                for (int k = 0; k < m; ++k) {
                    long long it = start_i + S[i] * D[k];
                    long long jt = start_j + S[j] * D[k];
                    if (it == jt) {
                        pl = k;
                    }
                }
                if (pl == -1)
                    return;  // 「少し広いところ以外で交わったらダメ
            }
        }
    }

    // 本当に m 箇所それぞれについて、3 個以上の馬車が交わることがないか確認
    for (int i = 0; i < m; ++i) {
        map<long long, int> ma;
        for (int j = 0; j < n; ++j) {
            long long t = uf.diff(0, j) + S[j] * D[i];
            ma[t]++;
        }
        for (map<long long, int>::iterator it = ma.begin(); it != ma.end(); ++it) {
            if (it->second >= 3)
                return;
        }
    }

    // 確認を終えたら OK
    if (res > ans)
        res = ans;
}

void dfs(vector<long long> diffs, int i, int j) {
    if (i == n - 1) {
        check(diffs);
        return;
    }

    // 馬車 i, j が何分でゴールするか
    long long total_i = S[i] * dist;
    long long total_j = S[j] * dist;

    // 次の index
    int ni = i;
    int nj = j + 1;
    if (nj == n) {
        ++ni;
        nj = ni + 1;
    }

    // weight(j) - weight(i) = 1 (j が i より 1 分遅れスタートで、途中で抜かさない場合
    if (total_j >= total_i - 1) {
        diffs.push_back(1);
        dfs(diffs, ni, nj);
        diffs.pop_back();
    }

    // ゴールでピッタリ
    {
        long long diff = total_i - total_j;
        if (diff >= 1) {
            diffs.push_back(diff);
            dfs(diffs, ni, nj);
            diffs.pop_back();
        }
    }

    // m 箇所それぞれ
    if (S[i] != S[j]) {
        for (int k = 0; k < m; ++k) {
            long long diff = (S[i] - S[j]) * D[k];
            if (diff >= 1) {
                diffs.push_back(diff);
                dfs(diffs, ni, nj);
                diffs.pop_back();
            }
        }
    }

    // それ以外
    diffs.push_back(-1);
    dfs(diffs, ni, nj);
    diffs.pop_back();
}

int main() {
    while (cin >> dist) {
        cin >> n;
        for (int i = 0; i < n; ++i)
            cin >> S[i];
        cin >> m;
        for (int i = 0; i < m; ++i)
            cin >> D[i];

        vector<long long> diffs;
        dfs(diffs, 0, 1);

        cout << res << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3460
final_rank: 8

code_snippet: #include <bits/stdc++.h>

// clang-format off
#define rep(i, s ,n) for(int i=s, i##_len=(n); i<i##_len; ++i)
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
using ll = long long;
// 2^60
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
using namespace std;
using Graph = vector<vector<int>>;
template <typename T> ostream &operator<<(ostream &s, vector<vector<vector<T>>> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << "[" << i << "]" << endl; s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<vector<T>> const &v) { for (int i = 0; i < int(v.size()); ++i ){ s << v[i];} return s;}
template <typename T> ostream &operator<<(ostream &s, vector<T> const &v) { for (int i = 0; i < int(v.size()); ++i) { s << v[i]; if (i != int(v.size()) - 1) { s << ",";}} s << endl; return s;}
// clang-format on

template <class Abel>
struct UnionFind {
    vector<int> par;
    vector<int> rank;
    vector<Abel> diff_weight;

    UnionFind(int n = 1, Abel SUM_UNITY = 0) {
        init(n, SUM_UNITY);
    }

    void init(int n = 1, Abel SUM_UNITY = 0) {
        par.resize(n);
        rank.resize(n);
        diff_weight.resize(n);
        for (int i = 0; i < n; ++i)
            par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;
    }

    int root(int x) {
        if (par[x] == x) {
            return x;
        } else {
            int r = root(par[x]);
            diff_weight[x] += diff_weight[par[x]];
            return par[x] = r;
        }
    }

    Abel weight(int x) {
        root(x);
        return diff_weight[x];
    }

    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    bool merge(int x, int y, Abel w) {
        w += weight(x);
        w -= weight(y);
        x = root(x);
        y = root(y);
        if (x == y)
            return false;
        if (rank[x] < rank[y])
            swap(x, y), w = -w;
        if (rank[x] == rank[y])
            ++rank[x];
        par[y] = x;
        diff_weight[y] = w;
        return true;
    }

    Abel diff(int x, int y) {
        return weight(y) - weight(x);
    }
};

typedef pair<int, int> pint;

long long dist;
int n, m;
long long S[11], D[11];

const long long INF = 1LL << 60;
long long res = INF;  // 答えを更新していく

// 各馬車が「どこですれ違うか」
void check(vector<long long> diffs) {
    UnionFind<long long> uf(n);
    int iter = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            long long diff = diffs[iter++];
            if (diff == -1)
                continue;

            if (uf.issame(i, j)) {
                long long curdiff = uf.diff(i, j);
                if (diff != curdiff)
                    return;
            } else {
                uf.merge(i, j, diff);
            }
        }
    }

    // 暫定回を求める
    long long start = 0, goal = 0;
    for (int i = 0; i < n; ++i) {
        long long start_i = start + uf.diff(0, i);
        long long goal_i = start_i + S[i] * dist;
        if (start > start_i)
            start = start_i;
        if (goal < goal_i)
            goal = goal_i;
    }

    // 整合性を確認
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            if (!uf.issame(i, j))
                return;  // 繋がっていない箇所があったら明らかに最適でないので return
            if (uf.diff(i, j) < 1)
                return;  // j が i の 1分後よりも早く出ていたらダメ

            // 追い越している場合はどこで追い越してるか
            long long start_i = uf.diff(0, i);
            long long goal_i = start_i + S[i] * dist;
            long long start_j = uf.diff(0, j);
            long long goal_j = start_j + S[j] * dist;
            if (goal_j < goal_i) {
                int pl = -1;
                for (int k = 0; k < m; ++k) {
                    long long it = start_i + S[i] * D[k];
                    long long jt = start_j + S[j] * D[k];
                    if (it == jt) {
                        pl = k;
                    }
                }
                if (pl == -1)
                    return;  // 「少し広いところ以外で交わったらダメ
            }
        }
    }

    // 本当に m 箇所それぞれについて、3 個以上の馬車が交わることがないか確認
    for (int i = 0; i < m; ++i) {
        map<long long, int> ma;
        for (int j = 0; j < n; ++j) {
            long long t = uf.diff(0, j) + S[j] * D[i];
            ma[t]++;
        }
        for (map<long long, int>::iterator it = ma.begin(); it != ma.end(); ++it) {
            if (it->second >= 3)
                return;
        }
    }

    // 確認を終えたら OK
    if (res > goal - start)
        res = goal - start;
}

void dfs(vector<long long> diffs, int i, int j) {
    if (i == n - 1) {
        check(diffs);
        return;
    }

    // 馬車 i, j が何分でゴールするか
    long long total_i = S[i] * dist;
    long long total_j = S[j] * dist;

    // 次の index
    int ni = i;
    int nj = j + 1;
    if (nj == n) {
        ++ni;
        nj = ni + 1;
    }

    // weight(j) - weight(i) = 1 (j が i より 1 分遅れスタートで、途中で抜かさない場合
    if (total_j >= total_i - 1) {
        diffs.push_back(1);
        dfs(diffs, ni, nj);
        diffs.pop_back();
    }

    // ゴールでピッタリ
    {
        long long diff = total_i - total_j;
        if (diff >= 1) {
            diffs.push_back(diff);
            dfs(diffs, ni, nj);
            diffs.pop_back();
        }
    }

    // m 箇所それぞれ
    if (S[i] != S[j]) {
        for (int k = 0; k < m; ++k) {
            long long diff = (S[i] - S[j]) * D[k];
            if (diff >= 1) {
                diffs.push_back(diff);
                dfs(diffs, ni, nj);
                diffs.pop_back();
            }
        }
    }

    // それ以外
    diffs.push_back(-1);
    dfs(diffs, ni, nj);
    diffs.pop_back();
}

int main() {
    while (cin >> dist) {
        cin >> n;
        for (int i = 0; i < n; ++i)
            cin >> S[i];
        cin >> m;
        for (int i = 0; i < m; ++i)
            cin >> D[i];

        vector<long long> diffs;
        dfs(diffs, 0, 1);

        cout << res << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3472
final_rank: 9

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}
int gcd(int a, int b) {
	if (a < b)swap(a, b);
	while (b) {
		int r = a % b; a = b; b = r;
	}
	return a;
}

struct ufundo {
private:
	vector<int> par, sz;
	vector<P> mem;
	vector<bool> united;
public:
	ufundo(int n) {
		par.resize(n, 0);
		sz.resize(n, 1);
		rep(i, n) {
			par[i] = i;
		}
	}
	int find(int x) {
		if (par[x] == x)return x;
		else return find(par[x]);
	}
	void unite(int x, int y) {
		x = find(x), y = find(y);
		if (x == y) {
			mem.push_back({ x,y });
			united.push_back(false);
			return;
		}
		united.push_back(true);
		if (sz[x] < sz[y]) {
			par[x] = y; sz[y] += sz[x];
			mem.push_back({ x,y });
		}
		else {
			par[y] = x; sz[x] += sz[y];
			mem.push_back({ y,x });
		}
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
	int getsize(int k) {
		return sz[k];
	}
	void undo() {
		assert(mem.size());
		P p = mem.back(); mem.pop_back();
		bool b = united.back(); united.pop_back();
		if (!b)return;
		int x = p.first, y = p.second;
		par[x] = x;
		sz[y] -= sz[x];
	}
};


struct edge {
	int to; ll dif;
};
void solve() {
	ll d; cin >> d;
	int n, m; cin >> n;
	vector <ll> s(n);
	rep(i, n)cin >> s[i];
	cin >> m;
	vector<ll> x(m);
	rep(j, m)cin >> x[j];
	ll ans = INF;
	auto upd = [&](vector<ll> t) {
		rep(i, n - 1)if (t[i] + 1 > t[i + 1])return;
		vector<set<ll>> cs(m);
		rep(i, n)Rep(j, i + 1, n) {
			if (s[i] > s[j]) {
				ll dif = t[j] - t[i];
				ll ds = s[i] - s[j];
				if (dif < ds * d) {
					if (dif % ds)return;
					ll loc = dif / ds;
					bool exi = false;
					rep(k, m)if (x[k] == loc) {
						ll val = t[i] + s[i] * x[k];
						if (cs[k].count(val))return;
						cs[k].insert(val);
						exi = true;
					}
					if (!exi)return;
				}
			}
		}

		ll ma = 0;
		rep(i, n) {
			ll val = t[i] + s[i] * d;
			ma = max(ma, val);
		}
		ans = min(ans, ma);
	};
	vector<int> cur;
	vector<P> vp;
	rep(i, n)Rep(j, i + 1, n)vp.push_back({ i,j });
	
	ufundo u(n);
	function<void(int)> dfs = [&](int dep) {
		if (dep == vp.size()) {
			vector<vector<edge>> G(n);
			rep(i, vp.size()) {
				if (cur[i] >= 0) {
					int a = vp[i].first;
					int b = vp[i].second;
					ll z = s[a] * x[cur[i]] - s[b] * x[cur[i]];
					G[a].push_back({ b,z });
					G[b].push_back({ a,-z });
				}
			}
			vector<bool> used(n);
			vector<ll> t(n);
			vector<int> ss;

			rep(i, n) {
				if (used[i])continue;
				ss.push_back(i);
				/*t[i] = 0;
				if (i > 0) {
					t[i] = t[i - 1] + 1;
					rep(j, i) {
						ll las = t[j]+s[j] * d - s[i] * d;
						t[i] = max(t[i], las);
					}
				}*/
				queue<int> q;
				q.push(i);
				used[i] = true;
				t[i] = 0;
				while (!q.empty()) {
					int id = q.front(); q.pop();
					for (edge e : G[id]) {
						if (!used[e.to]) {
							used[e.to] = true;
							t[e.to] = t[id] + e.dif;
							q.push(e.to);
						}
					}
				}
				int r = i + 1;
				while (r < n && used[r])r++;
			}
			rep(i, ss.size()) {
				int l = ss[i];
				int r = n; if (i + 1 < ss.size())r = ss[i + 1];
				//[l,r)
				if (l == 0)continue;
				ll ad2 = 0;
				ll clas = t[l] + s[l] * d;
				Rep(j, l, r) {
					ll las = t[j] + s[j] * d;
					ad2 = max(ad2, clas - las);
				}
				ll ad = t[l - 1]+1;
				rep(j, l) {
					ll las = t[j] + s[j] * d+ad2 - s[l] * d;
					ad = max(ad, las);
				}
				
				Rep(j, l, r)t[j] += ad;
			}
			//rep(i, ss.size())cout << ss[i] << " ";
			//cout << "\n";
			upd(t);

		}
		else {
			for (int i = -1; i < m; i++) {
				if (i >= 0) {
					int a = vp[dep].first;
					int b = vp[dep].second;
					if (u.same(a, b))continue;
					cur.push_back(i);
					u.unite(a, b);
					dfs(dep + 1);
					cur.pop_back();
					u.undo();
				}
				else {
					cur.push_back(i);
					dfs(dep + 1);
					cur.pop_back();
				}
			}
		}
	};
	dfs(0);
	cout << ans << "\n";
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
	//while (cin>>n>>m>>r,n)
		solve();
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 19860
final_rank: 14

code_snippet: #include<cstdlib>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<cstring>
#include<map>
using namespace std;
const int MAXN = (int) 105;
const int INF = (int) 0x3f3f3f3f;
typedef long long LL;

int dist;
int M,N;
int S[MAXN];
int D[MAXN];
LL ans;
LL out_time[MAXN];
map<LL,set<int> > mp;
struct permutation{
    int a[10];
}per;
int percnt;
vector<permutation> P;

bool is_judge(){
    mp.clear();
    for(int i=2;i<=N;i++)if(out_time[i]<=out_time[i-1]) return false;
    for(int i=1;i<N;i++){
        for(int j=i+1;j<=N;j++){
            if(S[i]<=S[j]) continue;
            if((out_time[j]-out_time[i])/(S[i]-S[j])>=dist) continue;
            if((out_time[j]-out_time[i])%(S[i]-S[j])!=0) return false;
            int tmpD=(out_time[j]-out_time[i])/(S[i]-S[j]);
            int ok=0;
            for(int k=1;k<=M;k++){
                if(D[k]==tmpD) ok=1;
            }
            if(!ok) return false;
            if(mp.count(tmpD)){
                if(mp[tmpD].count(i)) return false;
                if(mp[tmpD].count(j)) return false;
            }
            mp[tmpD].insert(i);
            mp[tmpD].insert(j);
        }
    }
    return true;
}

void update(){
    for(int i=N;i>=1;i--) out_time[i]-=out_time[1];
    if(!is_judge()) return;
    LL tmpans=0;
    for(int i=1;i<=N;i++){
        LL tmp=out_time[i]+(LL)dist*S[i];
        tmpans=max(tmpans,tmp);
    }
    ans=min(ans,tmpans);
}

int mark[MAXN];
void DFS1(int cur){
    if(cur>N){
        per.a[0]=1;
        P.push_back(per);
        return;
    }
    for(int i=1;i<=N;i++)if(!mark[i]){
        per.a[++percnt]=i;
        mark[i]=1;
        DFS1(cur+1);
        percnt--;
        mark[i]=0;
    }
}

void DFS2(int curid,const permutation& now){
    if(curid>N){
        update();
        return;
    }
    int cur=now.a[curid];
    if(curid==1){
        out_time[cur]=0;
        DFS2(curid+1,now);
        return;
    }

    for(int t=1;t<curid;t++){
        int pre=now.a[t];
        if(cur<pre){
            out_time[cur]=out_time[pre]-1;
            DFS2(curid+1,now);
            for(int i=1;i<=M;i++){
                LL dt=D[i];
                out_time[cur]=out_time[pre]-dt*(S[cur]-S[pre]);
    //            printf("%d-%d : %lld->%lld\n",pre,cur,out_time[pre],out_time[cur]);
                DFS2(curid+1,now);
            }
        }
        if(cur>pre){
            out_time[cur]=out_time[pre]+1;
            DFS2(curid+1,now);
            for(int i=1;i<=M;i++){
                LL dt=D[i];
                out_time[cur]=out_time[pre]+dt*(S[pre]-S[cur]);
                DFS2(curid+1,now);
            }
        }
    }
}

void solve(){
    for(int perid=0;perid<P.size();perid++){
        DFS2(1,P[perid]);
    }
}

void work(){
    scanf("%d%d",&dist,&N);
    for(int i=1;i<=N;i++) scanf("%d",&S[i]);
    scanf("%d",&M);
    for(int i=1;i<=M;i++) scanf("%d",&D[i]);
    D[++M]=dist;
    ans=(LL)INF*INF;
    DFS1(1);
    solve();
    printf("%lld\n",ans);
}

int main(){
#ifdef NNever
//freopen("data.in","r",stdin);
///freopen("out.txt","w",stdout);
#endif // NNever
    work();
    return 0;
}

/*
input
60516263
5
45
16
94
71
91
4
20586550
54017689
36941264
49153094

output
6577480535
*/
accuracy: 1
time_ms: 60
memory_kb: 3308
final_rank: 6

code_snippet: #include<cstdlib>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<cstring>
#include<map>
using namespace std;
const int MAXN = (int) 105;
const int INF = (int) 0x3f3f3f3f;
typedef long long LL;

int dist;
int M,N;
int S[MAXN];
int D[MAXN];
LL ans;
LL out_time[MAXN];
map<LL,set<int> > mp;
struct permutation{
    int a[10];
}per;
int percnt;
vector<permutation> P;

bool is_judge(){
    mp.clear();
    for(int i=2;i<=N;i++)if(out_time[i]<=out_time[i-1]) return false;
//    for(int i=1;i<=n;i++) printf("%lld ",out_time[i]);
//    printf("\n");
    for(int i=1;i<N;i++){
        for(int j=i+1;j<=N;j++){
            if(S[i]<=S[j]) continue;
            if((out_time[j]-out_time[i])/(S[i]-S[j])>=dist) continue;
            if((out_time[j]-out_time[i])%(S[i]-S[j])!=0) return false;
            int tmpD=(out_time[j]-out_time[i])/(S[i]-S[j]);
            int ok=0;
            for(int k=1;k<=M;k++){
                if(D[k]==tmpD) ok=1;
            }
//            printf("ok = %d! , tmpD = %-12d , i = %d , j = %d\n",ok,tmpD,i,j);
            if(!ok) return false;
            if(mp.count(tmpD)){
                if(mp[tmpD].count(i)) return false;
                if(mp[tmpD].count(j)) return false;
            }
            mp[tmpD].insert(i);
            mp[tmpD].insert(j);
        }
    }
    return true;
}

void update(){
    for(int i=N;i>=1;i--) out_time[i]-=out_time[1];
//    for(int i=1;i<N;i++)if(out_time[i]>=out_time[i+1]) return;
//    for(int i=1;i<=N;i++) printf("%lld ",out_time[i]);
//    printf("\n");
    if(!is_judge()) return;
    LL tmpans=0;
    for(int i=1;i<=N;i++){
        LL tmp=out_time[i]+(LL)dist*S[i];
        tmpans=max(tmpans,tmp);
    }
//    if(tmpans==6577480535){
//        for(int i=1;i<=N;i++) printf("%lld ",out_time[i]);
//        printf("\n");
//        if(is_judge()) printf("true!\n");
//        else printf("false!\n");
//        exit(0xff);
//    }
//    for(int i=1;i<=n;i++) printf("%lld ",out_time[i]);
//    printf(" : tmpans = %lld\n",tmpans);
    ans=min(ans,tmpans);
}

int mark[MAXN];
void DFS1(int cur){
    if(cur>N){
        per.a[0]=1;
        P.push_back(per);
        return;
    }
    for(int i=1;i<=N;i++)if(!mark[i]){
        per.a[++percnt]=i;
        mark[i]=1;
        DFS1(cur+1);
        percnt--;
        mark[i]=0;
    }
}

void DFS2(int curid,const permutation& now){
    if(curid>N){
        update();
        return;
    }
    int cur=now.a[curid];
    if(curid==1){
        out_time[cur]=0;
        DFS2(curid+1,now);
        return;
    }

    for(int t=1;t<curid;t++){
        int pre=now.a[t];
        if(cur<pre){
            out_time[cur]=out_time[pre]-1;
            DFS2(curid+1,now);
            for(int i=1;i<=M;i++){
                LL dt=D[i];
                out_time[cur]=out_time[pre]-dt*(S[cur]-S[pre]);
    //            printf("%d-%d : %lld->%lld\n",pre,cur,out_time[pre],out_time[cur]);
                DFS2(curid+1,now);
            }
        }
        if(cur>pre){
            out_time[cur]=out_time[pre]+1;
            DFS2(curid+1,now);
            for(int i=1;i<=M;i++){
                LL dt=D[i];
                out_time[cur]=out_time[pre]+dt*(S[pre]-S[cur]);
    //            printf("%d-%d : %lld->%lld\n",pre,cur,out_time[pre],out_time[cur]);
                DFS2(curid+1,now);
            }
        }
    }
}

void solve(){
    for(int perid=0;perid<P.size();perid++){
        DFS2(1,P[perid]);
    }
}

void work(){
    scanf("%d%d",&dist,&N);
    for(int i=1;i<=N;i++) scanf("%d",&S[i]);
    scanf("%d",&M);
    for(int i=1;i<=M;i++) scanf("%d",&D[i]);
    D[++M]=dist;
    ans=(LL)INF*INF;
    DFS1(1);
//    printf("Pcnt = %d\n",P.size());
//    for(int i=0;i<P.size();i++){
//        for(int k=1;k<=N;k++) printf("%d ",P[i].a[k]);
//        printf("\n");
//    }
    solve();
    printf("%lld\n",ans);
}

int main(){
#ifdef NNever
//freopen("data.in","r",stdin);
///freopen("out.txt","w",stdout);
#endif // NNever
    work();
    return 0;
}

/*
input
60516263
5
45
16
94
71
91
4
20586550
54017689
36941264
49153094

output
6577480535
*/
accuracy: 1
time_ms: 60
memory_kb: 3320
final_rank: 7

code_snippet: #include<cstdlib>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<cstring>
#include<map>
using namespace std;
const int MAXN = (int) 105;
const int INF = (int) 0x3f3f3f3f;
typedef long long LL;

int dist;
int M,N;
int S[MAXN];
int D[MAXN];
LL ans;
LL out_time[MAXN];
map<LL,int> mp;
struct permutation{
    int a[10];
}per;
int percnt;
vector<permutation> P;

bool is_judge(){
    mp.clear();
    for(int i=2;i<=N;i++)if(out_time[i]<=out_time[i-1]) return false;
//    for(int i=1;i<=n;i++) printf("%lld ",out_time[i]);
//    printf("\n");
    for(int i=1;i<=N;i++){
        for(int j=i+1;j<N;j++){
            if(S[i]<=S[j]) continue;
            if((out_time[j]-out_time[i])/(S[i]-S[j])>=dist) continue;
            if((out_time[j]-out_time[i])%(S[i]-S[j])!=0) return false;
            int tmpD=(out_time[j]-out_time[i])/(S[i]-S[j]);
            int ok=0;
            for(int k=1;k<=M;k++){
                if(D[k]==tmpD) ok=1;
            }
            if(!ok) return false;
            if(mp.count(tmpD)) return false;
            mp[tmpD]++;
        }
    }
    return true;
}

void update(){
    for(int i=N;i>=1;i--) out_time[i]-=out_time[1];
//    for(int i=1;i<N;i++)if(out_time[i]>=out_time[i+1]) return;
//    for(int i=1;i<=N;i++) printf("%lld ",out_time[i]);
//    printf("\n");
    if(!is_judge()) return;
    LL tmpans=0;
    for(int i=1;i<=N;i++){
        LL tmp=out_time[i]+(LL)dist*S[i];
        tmpans=max(tmpans,tmp);
    }
//    for(int i=1;i<=n;i++) printf("%lld ",out_time[i]);
//    printf(" : tmpans = %lld\n",tmpans);
    ans=min(ans,tmpans);
}

int mark[MAXN];
void DFS1(int cur){
    if(cur>N){
        per.a[0]=1;
        P.push_back(per);
        return;
    }
    for(int i=1;i<=N;i++)if(!mark[i]){
        per.a[++percnt]=i;
        mark[i]=1;
        DFS1(cur+1);
        percnt--;
        mark[i]=0;
    }
}

void DFS2(int curid,permutation now){
    if(curid>N){
        update();
        return;
    }
    int cur=now.a[curid];
    if(curid==1){
        out_time[cur]=0;
        DFS2(curid+1,now);
        return;
    }

    for(int t=1;t<curid;t++){
        int pre=now.a[t];
        if(cur<pre){
            out_time[cur]=out_time[pre]-1;
            DFS2(curid+1,now);
            for(int i=1;i<=M;i++){
                LL dt=D[i];
                out_time[cur]=out_time[pre]-dt*(S[cur]-S[pre]);
    //            printf("%d-%d : %lld->%lld\n",pre,cur,out_time[pre],out_time[cur]);
                DFS2(curid+1,now);
            }
        }
        if(cur>pre){
            out_time[cur]=out_time[pre]+1;
            DFS2(curid+1,now);
            for(int i=1;i<=M;i++){
                LL dt=D[i];
                out_time[cur]=out_time[pre]+dt*(S[pre]-S[cur]);
    //            printf("%d-%d : %lld->%lld\n",pre,cur,out_time[pre],out_time[cur]);
                DFS2(curid+1,now);
            }
        }
    }
}

void solve(){
    for(int perid=0;perid<P.size();perid++){
        permutation now=P[perid];
        DFS2(1,now);
    }
}

void work(){
    scanf("%d%d",&dist,&N);
    for(int i=1;i<=N;i++) scanf("%d",&S[i]);
    scanf("%d",&M);
    for(int i=1;i<=M;i++) scanf("%d",&D[i]);
    D[++M]=dist;
    ans=(LL)INF*INF;
    DFS1(1);
//    printf("Pcnt = %d\n",P.size());
//    for(int i=0;i<P.size();i++){
//        for(int k=1;k<=n;k++) printf("%d ",P[i].a[k]);
//        printf("\n");
//    }
    solve();
    printf("%lld\n",ans);
}

int main(){
#ifdef NNever
//freopen("data.in","r",stdin);
///freopen("out.txt","w",stdout);
#endif // NNever
    work();
    return 0;
}

/*
60516263
5
45
16
94
71
91
4
20586550
54017689
36941264
49153094
*/
accuracy: 0.3076923076923077
time_ms: 40
memory_kb: 3308
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

//INSERT ABOVE HERE
signed main(){
  Int dist;
  cin>>dist;
  Int n;
  cin>>n;
  vector<Int> s(n);
  for(Int i=0;i<n;i++) cin>>s[i];
  Int m;
  cin>>m;
  vector<Int> d(m);
  for(Int i=0;i<m;i++) cin>>d[i];

  const Int INF = 1e17;
  Int t[10][10];
  Int ans=INF;
  auto check=
    [&](){
      struct edge{
	Int from,to,cost;
	edge(Int from,Int to,Int cost):from(from),to(to),cost(cost){
	  //cout<<from<<" "<<to<<" "<<cost<<endl;
	}
      };
      vector<edge> es;
      
      for(Int i=1;i<n;i++){
	// p[i-1] + 1 <= p[i]
	// p[i-1] - p[i] <= -1
	es.emplace_back(i,i-1,-1);
      }
      vector<Int> cnt(m,0);
      for(Int i=0;i<n;i++){
	for(Int j=i+1;j<n;j++){
	  // j catch up i at t[i][j]
	  if(t[i][j]==m){
	    // dist * s[i] + p[i] <= dist * s[j] + p[j]
	    // p[i] - p[j] <= dist * s[j] - dist * s[i]	    
	    es.emplace_back(j,i,dist*(s[j]-s[i]));
	    continue;
	  }
	  cnt[t[i][j]]++;
	  if(cnt[t[i][j]]>1) return;
	  Int x=d[t[i][j]];
	  // x * s[i] + p[i] == x * s[j] + p[j]
	  // x * s[i] + p[i] <= x * s[j] + p[j]	  
	  // p[i] - p[j] <= x * s[j] - x * s[i]
	  es.emplace_back(j,i,x*(s[j]-s[i]));
	  // x * s[i] + p[i] >= x * s[j] + p[j]
	  // p[j] - p[i] <= x * s[i] - x * s[j]
	  es.emplace_back(i,j,x*(s[i]-s[j]));	  
	}
      }
      
      vector<Int> p(n,INF);
      // minimize p[n-1] - p[0]
      // maximize p[0] - p[n-1]
      p[n-1] = 0;
      Int flg=1;
      for(Int t=0;t<n*3;t++){
	flg=0;
	for(auto e:es){
	  if(p[e.from]+e.cost<p[e.to]){
	    p[e.to]=p[e.from]+e.cost;
	    flg=1;
	  }
	}	
      }
      if(flg) return;
      assert(p[n-1]==0);
      vector<Int> z(n);
      for(Int i=0;i<n;i++) z[i]=p[i]-p[0];
      Int res=0;
      for(Int i=0;i<n;i++) chmax(res,dist*s[i]+z[i]);
      chmin(ans,res);
      //for(Int i=0;i<n;i++) cout<<i<<":"<<z[i]<<endl;
      //cout<<res<<endl;
    };

  using P = pair<Int, Int>;
  vector<P> vp;
  for(Int i=0;i<n;i++)
    for(Int j=i+1;j<n;j++)
      vp.emplace_back(i,j);

  function<void(Int)> dfs=
    [&](Int x){
      if(x==(Int)vp.size()){
	check();
	return;
      }
      for(Int i=0;i<=m;i++){
	t[vp[x].first][vp[x].second]=i;
	dfs(x+1);
      }
    };
  
  dfs(0);
  cout<<ans<<endl;
  return 0;
}
accuracy: 0.3076923076923077
time_ms: 2630
memory_kb: 3096
final_rank: 19

code_snippet: #include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
using namespace std;


#define REP(i, s) for (int i = 0; i < s; ++i)
#define ALL(v) (v.begin(), v.end())
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s << endl; }



template<class Abel> struct UnionFind {
    vector<int> par;
    vector<int> rank;
    vector<Abel> diff_weight;
    
    UnionFind(int n = 1, Abel SUM_UNITY = 0) {
        init(n, SUM_UNITY);
    }
    
    void init(int n = 1, Abel SUM_UNITY = 0) {
        par.resize(n); rank.resize(n); diff_weight.resize(n);
        for (int i = 0; i < n; ++i) par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;
    }
    
    int root(int x) {
        if (par[x] == x) {
            return x;
        }
        else {
            int r = root(par[x]);
            diff_weight[x] += diff_weight[par[x]];
            return par[x] = r;
        }
    }
    
    Abel weight(int x) {
        root(x);
        return diff_weight[x];
    }
    
    bool issame(int x, int y) {
        return root(x) == root(y);
    }
    
    bool merge(int x, int y, Abel w) {
        w += weight(x); w -= weight(y);
        x = root(x); y = root(y);
        if (x == y) return false;
        if (rank[x] < rank[y]) swap(x, y), w = -w;
        if (rank[x] == rank[y]) ++rank[x];
        par[y] = x;
        diff_weight[y] = w;
        return true;
    }
    
    Abel diff(int x, int y) {
        return weight(y) - weight(x);
    }
    
    friend ostream& operator << (ostream& s, UnionFind uf) {
        map<int, vector<int> > res;
        for (int i = 0; i < uf.par.size(); ++i) {
            int r = uf.root(i);
            res[r].push_back(i);
        }
        for (map<int, vector<int> >::iterator it = res.begin(); it != res.end(); ++it) {
            s << endl;
            for (int j = 0; j < (int)it->second.size(); ++j) {
                s << it->second[j] << "(" << uf.weight(it->second[j]) << "), ";
            }
        }
        return s << endl;
    }
};

typedef pair<int,int> pint;

long long dist;
int n, m;
long long S[11], D[11];

const long long INF = 1LL<<60;
long long res = INF; // 答えを更新していく

// 各馬車が「どこですれ違うか」
void check(vector<long long> diffs) {
    UnionFind<long long> uf(n);
    int iter = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            long long diff = diffs[iter++];
            if (diff == -1) continue;
            
            if (uf.issame(i, j)) {
                long long curdiff = uf.diff(i, j);
                if (diff != curdiff) return;
            }
            else {
                uf.merge(i, j, diff);
            }
        }
    }

    // 暫定回を求める
    long long start = 0, goal = 0;
    for (int i = 0; i < n; ++i) {
        long long start_i = start + uf.diff(0, i);
        long long goal_i = start_i + S[i] * dist;
        if (start > start_i) start = start_i;
        if (goal < goal_i) goal = goal_i;
    }
    
    // 整合性を確認
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            if (!uf.issame(i, j)) return; // 繋がっていない箇所があったら明らかに最適でないので return
            if (uf.diff(i, j) < 1) return; // j が i の 1分後よりも早く出ていたらダメ
            
            // 追い越している場合はどこで追い越してるか
            long long start_i = uf.diff(0, i);
            long long goal_i = start_i + S[i] * dist;
            long long start_j = uf.diff(0, j);
            long long goal_j = start_j + S[j] * dist;
            if (goal_j < goal_i) {
                int pl = -1;
                for (int k = 0; k < m; ++k) {
                    long long it = start_i + S[i] * D[k];
                    long long jt = start_j + S[j] * D[k];
                    if (it == jt) {
                        pl = k;
                    }
                }
                if (pl == -1) return; // 「少し広いところ以外で交わったらダメ
            }
        }
    }
    
    // 本当に m 箇所それぞれについて、3 個以上の馬車が交わることがないか確認
    for (int i = 0; i < m; ++i) {
        map<long long,int> ma;
        for (int j = 0; j < n; ++j) {
            long long t = uf.diff(0, j) + S[j] * D[i];
            ma[t]++;
        }
        for (map<long long,int>::iterator it = ma.begin(); it != ma.end(); ++it) {
            if (it->second >= 3) return;
        }
    }
    
    /*
    COUT("--------------");
    COUT(diffs);
    COUT(uf);
    COUT(start);
    COUT(goal);
    */
    
    // 確認を終えたら OK
    if (res > goal - start) res = goal - start;
}

void dfs(vector<long long> diffs, int i, int j) {
    if (i == n-1) {
        check(diffs);
        return;
    }
    
    // 馬車 i, j が何分でゴールするか
    long long total_i = S[i] * dist;
    long long total_j = S[j] * dist;
    
    // 次の index
    int ni = i;
    int nj = j+1;
    if (nj == n) {
        ++ni;
        nj = ni+1;
    }
    
    // weight(j) - weight(i) = 1 (j が i より 1 分遅れスタートで、途中で抜かさない場合
    if (total_j >= total_i - 1) {
        diffs.push_back(1);
        dfs(diffs, ni, nj);
        diffs.pop_back();
    }
    
    // ゴールでピッタリ
    {
        long long diff = total_i - total_j;
        if (diff >= 1) {
            diffs.push_back(diff);
            dfs(diffs, ni, nj);
            diffs.pop_back();
        }
    }
    
    // m 箇所それぞれ
    if (S[i] != S[j]) {
        for (int k = 0; k < m; ++k) {
            long long diff = (S[i] - S[j]) * D[k];
            if (diff >= 1) {
                diffs.push_back(diff);
                dfs(diffs, ni, nj);
                diffs.pop_back();
            }
        }
    }
    
    // それ以外
    diffs.push_back(-1);
    dfs(diffs, ni, nj);
    diffs.pop_back();
}

int main() {
    while (cin >> dist) {
        cin >> n;
        for (int i = 0; i < n; ++i) cin >> S[i];
        cin >> m;
        for (int i = 0; i < m; ++i) cin >> D[i];
        
        vector<long long> diffs;
        dfs(diffs, 0, 1);
        
        cout << res << endl;
    }
}
accuracy: 1
time_ms: 120
memory_kb: 3176
final_rank: 11

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#pragma warning(disable:4996)
using namespace std;

const long long int My_LInf=9223372036854775807;


struct aUnionFind {
	vector<pair<int, long long int>> data;
	aUnionFind(int size) : data(size, make_pair(-1, 0)) { }

	//y is w bigger than x
	bool unionSet(const int x, const int y, const long long int w) {
		const int rx(root(x).first), ry(root(y).first);
		if (rx != ry) {
			data[rx].first += data[ry].first; data[ry].first = rx;
			data[ry].second = w + data[x].second - data[y].second;
			return true;
		}
		else {
			return root(x).second + w == root(y).second;
		}
	}
	bool findSet(const int x, const int y) {
		return root(x) == root(y);
	}

	//x is belong to first
	//x is second bigger than first
	pair<int, long long int> root(const int x) {
		if (data[x].first < 0) {
			return make_pair(x, 0);
		}
		else {
			pair<int, long long int>ndata;
			ndata.first = root(data[x].first).first;
			ndata.second = data[x].second + root(data[x].first).second;
			return data[x] = ndata;
		}
	}
	int size(const int x) {
		return -data[root(x).first].first;
	}
};


int HorseNum, M;

vector<long long int>sps;

struct aa {
	int fstfinid;
	long long int fstfintime;
	int lasfinid;
	long long int lasfintime;
	int fststaid;
	long long int fststatime;
	int lasstaid;
	long long int lasstatime;
};


long long int check(const vector<vector<bool>>&changes, const vector<vector<long long int>>&times) {
	vector<int>seq(HorseNum);
	iota(seq.begin(), seq.end(), 0);
	aUnionFind uf(HorseNum);
	for (int wide = 0; wide < M; ++wide) {
		for (int change = 0; change < HorseNum - 1; ++change) {
			if (changes[wide][change]) {
				const int c0 = seq[change];
				const int c1 = seq[change + 1];
				const long long int  sa = times[c0][wide] - times[c1][wide];
				if (sa > 0) {
					if (!uf.unionSet(c0, c1, sa)) {
						return My_LInf;
					}
				}
				else {
					return My_LInf;
				}
				swap(seq[change], seq[change + 1]);
			}
		}
	}

	map<int, aa>mp;
	for (int i = 0; i < HorseNum; ++i) {
		if (!mp.count(uf.root(i).first)) {
			mp[uf.root(i).first] = aa{
			i,uf.root(i).second + times[i][M],
			i,uf.root(i).second + times[i][M],
			i,0,
			i,0,
			};
		}
		else {
			if (mp[uf.root(i).first].fstfintime > uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].fstfinid = i;
				mp[uf.root(i).first].fstfintime = uf.root(i).second + times[i][M];
			}
			if (mp[uf.root(i).first].lasfintime < uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].lasfinid = i;
				mp[uf.root(i).first].lasfintime = uf.root(i).second + times[i][M];
			}
			mp[uf.root(i).first].lasstaid = i;
			mp[uf.root(i).first].lasstatime = uf.root(i).second;
		}
	}
	for (auto it = mp.begin(); it != mp.end(); ++it) {
		if (it != mp.begin()) {
			aa afrom(prev(it)->second);
			aa ato(it->second);

			if (afrom.lasfintime - afrom.lasstatime>ato.fstfintime-ato.fststatime) {
				uf.unionSet(afrom.lasfinid, ato.fstfinid, times[afrom.lasfinid][M] - times[ato.fstfinid][M]);
			}
			else {
				uf.unionSet(afrom.lasstaid, ato.fststaid, 1);
			}
		}
	}
	for (int i = 0; i < HorseNum - 1; ++i) {
		if (uf.root(i).second >= uf.root(i + 1).second)return My_LInf;
	}
	for (int i = 0; i < HorseNum - 1; ++i) {
		if (uf.root(seq[i]).second+times[seq[i]][M] > uf.root(seq[i + 1]).second + times[seq[i+1]][M])return My_LInf;
	}
	long long int amax = 0;
	for (int i = 0; i <HorseNum; ++i) {
		amax = max(amax, uf.root(i).second + times[i][M] - uf.root(0).second);
	}
	return amax;
}

int main() {
	long long int dist;
	cin >> dist;

	cin >> HorseNum;
	for (int i = 0; i <HorseNum; ++i) {
		int S; cin >> S;
		sps.push_back(S);
	}
	cin >> M;
	vector<long long int>ds;
	for (int i = 0; i < M; ++i) {
		int D; cin >> D;
		ds.push_back(D);
	}
	sort(ds.begin(), ds.end());
	vector<vector<long long int>>times(HorseNum, vector<long long int>(M + 1));
	for (int i = 0; i <HorseNum; ++i) {
		for (int j = 0; j < M; ++j) {
			times[i][j] = sps[i] * ds[j];
		}
		times[i][M] = sps[i] * dist;
	}
	long long int ans = My_LInf;
	for (int i = 0; i < 1<<((HorseNum-1)*M); ++i) {
		bitset<20>bs(i);
		vector<vector<bool>>changes(M, vector<bool>(HorseNum -1));
		bool ok = true;
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 1; ++k) {
				changes[j][k] = bs[j*(HorseNum - 1) + k];
			}
		}
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 2; ++k) {
				if (changes[j][k] && changes[j][k + 1]) {
					ok = false;
					break;
				}
			}
		}
		if (!ok)continue;
		long long int a = check(changes, times);
		if (a < ans) {
			ans = a;
		}
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 3176
final_rank: 12

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#pragma warning(disable:4996)
using namespace std;

const long long int My_LInf=9223372036854775807;


struct aUnionFind {
	vector<pair<int, long long int>> data;
	aUnionFind(int size) : data(size, make_pair(-1, 0)) { }

	//y is w bigger than x
	bool unionSet(const int x, const int y, const long long int w) {
		const int rx(root(x).first), ry(root(y).first);
		if (rx != ry) {
			data[rx].first += data[ry].first; data[ry].first = rx;
			data[ry].second = w + data[x].second - data[y].second;
			return true;
		}
		else {
			return root(x).second + w == root(y).second;
		}
	}
	bool findSet(const int x, const int y) {
		return root(x) == root(y);
	}

	//x is belong to first
	//x is second bigger than first
	pair<int, long long int> root(const int x) {
		if (data[x].first < 0) {
			return make_pair(x, 0);
		}
		else {
			pair<int, long long int>ndata;
			ndata.first = root(data[x].first).first;
			ndata.second = data[x].second + root(data[x].first).second;
			return data[x] = ndata;
		}
	}
	int size(const int x) {
		return -data[root(x).first].first;
	}
};


int HorseNum, M;

vector<long long int>sps;

struct aa {
	int fstfinid;
	long long int fstfintime;
	int lasfinid;
	long long int lasfintime;
	int fststaid;
	long long int fststatime;
	int lasstaid;
	long long int lasstatime;
};


long long int check(const vector<vector<bool>>&changes, const vector<vector<long long int>>&times) {
	vector<int>seq(HorseNum);
	iota(seq.begin(), seq.end(), 0);
	aUnionFind uf(HorseNum);
	for (int wide = 0; wide < M; ++wide) {
		for (int change = 0; change < HorseNum - 1; ++change) {
			if (changes[wide][change]) {
				const int c0 = seq[change];
				const int c1 = seq[change + 1];
				const long long int  sa = times[c0][wide] - times[c1][wide];
				if (sa > 0) {
					if (!uf.unionSet(c0, c1, sa)) {
						return My_LInf;
					}
				}
				else {
					return My_LInf;
				}
				swap(seq[change], seq[change + 1]);
			}
		}
	}

	map<int, aa>mp;
	for (int i = 0; i < HorseNum; ++i) {
		if (!mp.count(uf.root(i).first)) {
			mp[uf.root(i).first] = aa{
			i,uf.root(i).second + times[i][M],
			i,uf.root(i).second + times[i][M],
			i,0,
			i,0,
			};
		}
		else {
			if (mp[uf.root(i).first].fstfintime > uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].fstfinid = i;
				mp[uf.root(i).first].fstfintime = uf.root(i).second + times[i][M];
			}
			if (mp[uf.root(i).first].lasfintime < uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].lasfinid = i;
				mp[uf.root(i).first].lasfintime = uf.root(i).second + times[i][M];
			}
			mp[uf.root(i).first].lasstaid = i;
			mp[uf.root(i).first].lasstatime = uf.root(i).second;
		}
	}
	for (auto it = mp.begin(); it != mp.end(); ++it) {
		if (it != mp.begin()) {
			aa afrom(prev(it)->second);
			aa ato(it->second);

			if (afrom.lasfintime - afrom.lasstatime>ato.fstfintime-ato.fststatime) {
				uf.unionSet(afrom.lasfinid, ato.fstfinid, times[afrom.lasfinid][M] - times[ato.fstfinid][M]);
			}
			else {
				uf.unionSet(afrom.lasstaid, ato.fststaid, 1);
			}
			/*aUnionFind auf(uf);
			aUnionFind buf(uf);
			{
				int from = (prev(it))->second.lasfinid;
				int to = (it)->second.fstfinid;

				if (sps[from] > sps[to]) {
					auf.unionSet(from, to, times[from][M] - times[to][M]);
				}
				else {
					auf.unionSet((prev(it))->second.lasstaid, (it)->second.fststaid, 1);
				}
			}
			{
				int from = (prev(it))->second.lasstaid;
				int to = (it)->second.fststaid;
				buf.unionSet(from, to, 1);
				
			}

			if (buf.root((it)->second.fststaid).second > auf.root((it)->second.fststaid).second) {
				uf = buf;
			}
			else {
				uf = auf;
			}*/
		}
	}
	for (int i = 0; i < HorseNum - 1; ++i) {
		if (uf.root(i).second >= uf.root(i + 1).second)return My_LInf;
	}
	for (int i = 0; i < HorseNum - 1; ++i) {
		if (uf.root(seq[i]).second+times[seq[i]][M] > uf.root(seq[i + 1]).second + times[seq[i+1]][M])return My_LInf;
	}
	long long int amax = 0;
	for (int i = 0; i <HorseNum; ++i) {
		amax = max(amax, uf.root(i).second + times[i][M] - uf.root(0).second);
	}
	return amax;
}

int main() {
	aUnionFind uu(10);
	uu.unionSet(0, 1, 3);
	uu.unionSet(0, 2, 4);
	uu.unionSet(2, 4, 5);
	uu.unionSet(6, 7, 1);
	uu.unionSet(7, 8, 2);
	uu.unionSet(0, 8, 0);
	
	
	long long int dist;
	cin >> dist;

	cin >> HorseNum;
	for (int i = 0; i <HorseNum; ++i) {
		int S; cin >> S;
		sps.push_back(S);
	}
	cin >> M;
	vector<long long int>ds;
	for (int i = 0; i < M; ++i) {
		int D; cin >> D;
		ds.push_back(D);
	}
	sort(ds.begin(), ds.end());
	vector<vector<long long int>>times(HorseNum, vector<long long int>(M + 1));
	for (int i = 0; i <HorseNum; ++i) {
		for (int j = 0; j < M; ++j) {
			times[i][j] = sps[i] * ds[j];
		}
		times[i][M] = sps[i] * dist;
	}
	long long int ans = My_LInf;
	for (int i = 0; i < 1<<((HorseNum-1)*M); ++i) {
		bitset<20>bs(i);
		vector<vector<bool>>changes(M, vector<bool>(HorseNum -1));
		bool ok = true;
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 1; ++k) {
				changes[j][k] = bs[j*(HorseNum - 1) + k];
			}
		}
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 2; ++k) {
				if (changes[j][k] && changes[j][k + 1]) {
					ok = false;
					break;
				}
			}
		}
		if (!ok)continue;
		long long int a = check(changes, times);
		if (a < ans) {
			ans = a;
		}
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 330
memory_kb: 3180
final_rank: 13

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#pragma warning(disable:4996)
using namespace std;

const long long int My_LInf=9223372036854775807;


struct aUnionFind {
	vector<pair<int, long long int>> data;
	aUnionFind(int size) : data(size, make_pair(-1, 0)) { }

	//y is w bigger than x
	bool unionSet(const int x, const int y, const long long int w) {
		const int rx(root(x).first), ry(root(y).first);
		if (rx != ry) {
			data[rx].first += data[ry].first; data[ry].first = rx;
			data[ry].second = w + data[x].second - data[y].second;
			return true;
		}
		else {
			return root(x).second + w == root(y).second;
		}
	}
	bool findSet(const int x, const int y) {
		return root(x) == root(y);
	}

	//x is belong to first
	//x is second bigger than first
	pair<int, long long int> root(const int x) {
		if (data[x].first < 0) {
			return make_pair(x, 0);
		}
		else {
			pair<int, long long int>ndata;
			ndata.first = root(data[x].first).first;
			ndata.second = data[x].second + root(data[x].first).second;
			return data[x] = ndata;
		}
	}
	int size(const int x) {
		return -data[root(x).first].first;
	}
};


int HorseNum, M;

vector<long long int>sps;

struct aa {
	int fstfinid;
	long long int fstfintime;
	int lasfinid;
	long long int lasfintime;
	int fststaid;
	long long int fststatime;
	int lasstaid;
	long long int lasstatime;
};


long long int check(const vector<vector<bool>>&changes, const vector<vector<long long int>>&times) {
	vector<int>seq(HorseNum);
	iota(seq.begin(), seq.end(), 0);
	aUnionFind uf(HorseNum);
	for (int wide = 0; wide < M; ++wide) {
		for (int change = 0; change < HorseNum - 1; ++change) {
			if (changes[wide][change]) {
				const int c0 = seq[change];
				const int c1 = seq[change + 1];
				const long long int  sa = times[c0][wide] - times[c1][wide];
				if (sa > 0) {
					if (!uf.unionSet(c0, c1, sa)) {
						return My_LInf;
					}
				}
				else {
					return My_LInf;
				}
				swap(seq[change], seq[change + 1]);
			}
		}
	}

	map<int, aa>mp;
	for (int i = 0; i < HorseNum; ++i) {
		if (!mp.count(uf.root(i).first)) {
			mp[uf.root(i).first] = aa{
			i,uf.root(i).second + times[i][M],
			i,uf.root(i).second + times[i][M],
			i,0,
			i,0,
			};
		}
		else {
			if (mp[uf.root(i).first].fstfintime > uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].fstfinid = i;
				mp[uf.root(i).first].fstfintime = uf.root(i).second + times[i][M];
			}
			if (mp[uf.root(i).first].lasfintime < uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].lasfinid = i;
				mp[uf.root(i).first].lasfintime = uf.root(i).second + times[i][M];
			}
			mp[uf.root(i).first].lasstaid = i;
			mp[uf.root(i).first].lasstatime = uf.root(i).second;
		}
	}
	for (auto it = mp.begin(); it != mp.end(); ++it) {
		if (it != mp.begin()) {
			aa afrom(prev(it)->second);
			aa ato(it->second);

			if (afrom.lasfintime - afrom.lasstatime>ato.fstfintime-ato.fststatime) {
				uf.unionSet(afrom.lasfinid, ato.fstfinid, times[afrom.lasfinid][M] - times[ato.fstfinid][M]);
			}
			else {
				uf.unionSet(afrom.lasstaid, ato.fststaid, 1);
			}
			/*aUnionFind auf(uf);
			aUnionFind buf(uf);
			{
				int from = (prev(it))->second.lasfinid;
				int to = (it)->second.fstfinid;

				if (sps[from] > sps[to]) {
					auf.unionSet(from, to, times[from][M] - times[to][M]);
				}
				else {
					auf.unionSet((prev(it))->second.lasstaid, (it)->second.fststaid, 1);
				}
			}
			{
				int from = (prev(it))->second.lasstaid;
				int to = (it)->second.fststaid;
				buf.unionSet(from, to, 1);
				
			}

			if (buf.root((it)->second.fststaid).second > auf.root((it)->second.fststaid).second) {
				uf = buf;
			}
			else {
				uf = auf;
			}*/
		}
	}
	for (int i = 0; i < HorseNum - 1; ++i) {
		if (uf.root(i).second >= uf.root(i + 1).second)return My_LInf;
	}
	long long int amax = 0;
	for (int i = 0; i <HorseNum; ++i) {
		amax = max(amax, uf.root(i).second + times[i][M] - uf.root(0).second);
	}
	return amax;
}

int main() {
	
	
	long long int dist;
	cin >> dist;

	cin >> HorseNum;
	for (int i = 0; i <HorseNum; ++i) {
		int S; cin >> S;
		sps.push_back(S);
	}
	cin >> M;
	vector<long long int>ds;
	for (int i = 0; i < M; ++i) {
		int D; cin >> D;
		ds.push_back(D);
	}
	sort(ds.begin(), ds.end());
	vector<vector<long long int>>times(HorseNum, vector<long long int>(M + 1));
	for (int i = 0; i <HorseNum; ++i) {
		for (int j = 0; j < M; ++j) {
			times[i][j] = sps[i] * ds[j];
		}
		times[i][M] = sps[i] * dist;
	}
	long long int ans = My_LInf;
	for (int i = 0; i < 1<<((HorseNum-1)*M); ++i) {
		bitset<20>bs(i);
		vector<vector<bool>>changes(M, vector<bool>(HorseNum -1));
		bool ok = true;
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 1; ++k) {
				changes[j][k] = bs[j*(HorseNum - 1) + k];
			}
		}
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 2; ++k) {
				if (changes[j][k] && changes[j][k + 1]) {
					ok = false;
					break;
				}
			}
		}
		if (!ok)continue;
		long long int a = check(changes, times);
		ans = min(ans,a);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 0.46153846153846156
time_ms: 330
memory_kb: 3180
final_rank: 17

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#pragma warning(disable:4996)
using namespace std;

const long long int My_LInf=9223372036854775807;


struct aUnionFind {
	vector<pair<int, long long int>> data;
	aUnionFind(int size) : data(size, make_pair(-1, 0)) { }

	//y is w bigger than x
	bool unionSet(const int x, const int y, const long long int w) {
		const int rx(root(x).first), ry(root(y).first);
		if (rx != ry) {
			data[rx].first += data[ry].first; data[ry].first = rx;
			data[ry].second = w + data[x].second - data[y].second;
			return true;
		}
		else {
			return root(x).second + w == root(y).second;
		}
	}
	bool findSet(const int x, const int y) {
		return root(x) == root(y);
	}

	//x is belong to first
	//x is second bigger than first
	pair<int, long long int> root(const int x) {
		if (data[x].first < 0) {
			return make_pair(x, 0);
		}
		else {
			pair<int, long long int>ndata;
			ndata.first = root(data[x].first).first;
			ndata.second = data[x].second + root(data[x].first).second;
			return data[x] = ndata;
		}
	}
	int size(const int x) {
		return -data[root(x).first].first;
	}
};


int HorseNum, M;

vector<long long int>sps;

struct aa {
	int fstfinid;
	long long int fstfintime;
	int lasfinid;
	long long int lasfintime;
	int fststaid;
	long long int fststatime;
	int lasstaid;
	long long int lasstatime;
};


long long int check(const vector<vector<bool>>&changes, const vector<vector<long long int>>&times) {
	vector<int>seq(HorseNum);
	iota(seq.begin(), seq.end(), 0);
	aUnionFind uf(HorseNum);
	for (int wide = 0; wide < M; ++wide) {
		for (int change = 0; change < HorseNum - 1; ++change) {
			if (changes[wide][change]) {
				const int c0 = seq[change];
				const int c1 = seq[change + 1];
				const long long int  sa = times[c0][wide] - times[c1][wide];
				if (sa > 0) {
					if (!uf.unionSet(c0, c1, sa)) {
						return My_LInf;
					}
				}
				else {
					return My_LInf;
				}
				swap(seq[change], seq[change + 1]);
			}
		}
	}
	map<int, aa>mp;
	for (int i = 0; i < HorseNum; ++i) {
		if (!mp.count(uf.root(i).first)) {
			mp[uf.root(i).first] = aa{
			i,uf.root(i).second + times[i][M],
			i,uf.root(i).second + times[i][M],
			i,0,
			i,0,
			};
		}
		else {
			if (mp[uf.root(i).first].fstfintime > uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].fstfinid = i;
				mp[uf.root(i).first].fstfintime = uf.root(i).second + times[i][M];
			}
			if (mp[uf.root(i).first].lasfintime < uf.root(i).second + times[i][M]) {
				mp[uf.root(i).first].lasfinid = i;
				mp[uf.root(i).first].lasfintime = uf.root(i).second + times[i][M];
			}
			mp[uf.root(i).first].lasstaid = i;
			mp[uf.root(i).first].lasstatime = uf.root(i).second;
		}
	}
	for (auto it = mp.begin(); it != mp.end(); ++it) {
		if (it != mp.begin()) {
			aa afrom(prev(it)->second);
			aa ato(it->second);

			if (afrom.lasfintime - afrom.lasstatime>ato.fstfintime-ato.fststatime) {
				uf.unionSet(afrom.lasfinid, ato.fstfinid, times[afrom.lasfinid][M] - times[ato.fstfinid][M]);
			}
			else {
				uf.unionSet(afrom.lasstaid, ato.fststaid, 1);
			}
			/*aUnionFind auf(uf);
			aUnionFind buf(uf);
			{
				int from = (prev(it))->second.lasfinid;
				int to = (it)->second.fstfinid;

				if (sps[from] > sps[to]) {
					auf.unionSet(from, to, times[from][M] - times[to][M]);
				}
				else {
					auf.unionSet((prev(it))->second.lasstaid, (it)->second.fststaid, 1);
				}
			}
			{
				int from = (prev(it))->second.lasstaid;
				int to = (it)->second.fststaid;
				buf.unionSet(from, to, 1);
				
			}

			if (buf.root((it)->second.fststaid).second > auf.root((it)->second.fststaid).second) {
				uf = buf;
			}
			else {
				uf = auf;
			}*/
		}
	}
	for (int i = 0; i < HorseNum - 1; ++i) {
		if (uf.root(i).second >= uf.root(i + 1).second)return My_LInf;
	}
	long long int amax = 0;
	for (int i = 0; i <HorseNum; ++i) {
		amax = max(amax, uf.root(i).second + times[i][M] - uf.root(0).second);
	}
	return amax;
}

int main() {
	
	
	long long int dist;
	cin >> dist;

	cin >> HorseNum;
	for (int i = 0; i <HorseNum; ++i) {
		int S; cin >> S;
		sps.push_back(S);
	}
	cin >> M;
	vector<long long int>ds;
	for (int i = 0; i < M; ++i) {
		int D; cin >> D;
		ds.push_back(D);
	}
	vector<vector<long long int>>times(HorseNum, vector<long long int>(M + 1));
	for (int i = 0; i <HorseNum; ++i) {
		for (int j = 0; j < M; ++j) {
			times[i][j] = sps[i] * ds[j];
		}
		times[i][M] = sps[i] * dist;
	}
	long long int ans = My_LInf;
	for (int i = 0; i < 1<<((HorseNum-1)*M); ++i) {
		bitset<20>bs(i);
		vector<vector<bool>>changes(M, vector<bool>(HorseNum -1));
		bool ok = true;
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 1; ++k) {
				changes[j][k] = bs[j*(HorseNum - 1) + k];
			}
		}
		for (int j = 0; j < M; ++j) {
			for (int k = 0; k < HorseNum - 2; ++k) {
				if (changes[j][k] && changes[j][k + 1]) {
					ok = false;
					break;
				}
			}
		}
		if (!ok)continue;
		long long int a = check(changes, times);
		ans = min(ans,a);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 0.46153846153846156
time_ms: 320
memory_kb: 3180
final_rank: 16

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
long long p[10];
long long q[10];
struct wolf{
	int p[5];
	wolf(){}
};
wolf now[6];
int N,M;
int rev[10][10];
int perm[10][10];
long long INF=9999999999999999LL;
long long t[10][10];
long long dfs(int a){
	if(a==M){
		for(int i=0;i<=M+1;i++){
			for(int j=0;j<N;j++){
				t[i][j]=j+p[j]*q[i];
			}
		}
		int cnt=0;
		while(1){
			bool chg=false;
			for(int i=0;i<=M;i++){
				for(int j=0;j<N;j++){
					for(int k=j+1;k<N;k++){
						if(t[i][now[i].p[j]]+p[now[i].p[j]]*(q[i+1]-q[i])>t[i][now[i].p[k]]+p[now[i].p[k]]*(q[i+1]-q[i])){
							chg=true;
							t[i][now[i].p[k]]=t[i][now[i].p[j]]+p[now[i].p[j]]*(q[i+1]-q[i])-p[now[i].p[k]]*(q[i+1]-q[i]);
							for(int l=0;l<=M+1;l++)t[l][now[i].p[k]]=t[i][now[i].p[k]]+p[now[i].p[k]]*(q[l]-q[i]);
						}
						if(t[i][now[i].p[j]]>t[i][now[i].p[k]]){
							chg=true;
							t[i][now[i].p[k]]=t[i][now[i].p[j]];
							for(int l=0;l<=M+1;l++)t[l][now[i].p[k]]=t[i][now[i].p[k]]+p[now[i].p[k]]*(q[l]-q[i]);
						}
						if(i==0&&t[i][now[i].p[j]]>=t[i][now[i].p[k]]){
							chg=true;
							for(int l=0;l<=M+1;l++)t[l][now[i].p[k]]=t[i][now[i].p[j]]+1+p[now[i].p[k]]*(q[l]-q[i]);
						}
					}
				}
			}
			cnt++;
			if(cnt==200)return INF;
			//long long tmp=0;
			//for(int i=0;i<N;i++)tmp=max(tmp,t[M+1][i]);
			//printf("%lld\n",tmp);
			if(!chg)break;
		}
		long long ret=0;
		for(int i=0;i<N;i++)ret=max(ret,t[M+1][i]);
		/*if(ret==382){
			for(int i=0;i<=M;i++){
				for(int j=0;j<N;j++)printf("%d ",now[i].p[j]);
				printf("\n");
			}
			for(int i=0;i<=M+1;i++){
				for(int j=0;j<N;j++)printf("%lld ",t[i][j]);
				printf("\n");
			}
		}*/
		return ret;
	}
	long long ret=INF;
	for(int i=0;i<N;i++){
		perm[a][i]=i;
		rev[a][now[a].p[i]]=i;
	}
	do{
		bool ok=true;
		for(int i=0;i<N;i++){
			if(rev[a][perm[a][i]]>i+1)ok=false;
			if(rev[a][perm[a][i]]<i-1)ok=false;
			for(int j=i+1;j<N;j++){
				if(rev[a][perm[a][i]]>rev[a][perm[a][j]]&&p[perm[a][i]]>=p[perm[a][j]])ok=false;
			}
		}
		if(ok){
			for(int i=0;i<N;i++)now[a+1].p[i]=perm[a][i];
			ret=min(ret,dfs(a+1));
		}
	}while(next_permutation(perm[a],perm[a]+N));
	return ret;
}
int main(){
	int a,b,c;
	scanf("%d%d",&a,&b);
	for(int i=0;i<b;i++)scanf("%lld",p+i);
	scanf("%d",&c);
	N=b;M=c;
	for(int i=0;i<c;i++)scanf("%lld",q+i+1);
	std::sort(q,q+c+1);
	q[c+1]=a;
	for(int i=0;i<b;i++){
		now[0].p[i]=i;
	}
	printf("%lld\n",dfs(0));
}
accuracy: 1
time_ms: 10
memory_kb: 1032
final_rank: 1

code_snippet: /*
    ?????????????????¨??????
*/

#define __1__

#ifdef __1__
#include <iostream>
#include <cstdio>
#include <algorithm>
#define rep(i,n) for(int i = 0;i < (n);i++)
#define _MAX 7
#define INF 7e10
#define MIN(a,b) (a)>(b)?(b):(a)
using namespace std;
typedef long long int lint;


int dist,n,m;
lint tm[_MAX][_MAX+2]; //tm[][0]?????????????????????,tm[][m+1]???????????´??????
lint S[_MAX];
lint D[_MAX];

lint rettm(){
    lint ans = 0;
    rep(i,n){
        ans = max(ans,tm[i][m+1]);
    }
    return ans;
}

void maketm(int x){
    rep(i,m){
        tm[x][i+1]=tm[x][0]+D[i]*S[x];
    }
    tm[x][m+1]=tm[x][0]+S[x]*dist;
    return;
}

void show(){
    rep(i,n){
        rep(j,m+2){
            printf("%4lld ",tm[i][j]);
        }
        cout << endl;
    }
    cout << endl;
    return;
}

int flag[5]={0};

bool check(){
    rep(i,n-1){
        if(tm[i][0]>=tm[i+1][0]){
            return false;
        }
    }
    rep(i,n){
        rep(j,n){
            if(i<j&&tm[i][m+1]>tm[j][m+1]){
                bool hoge = 0;
                rep(k,m){
                    if(tm[i][k+1]==tm[j][k+1]){
                        rep(l,n){
                            if(l!=i&&l!=j&&tm[i][k+1]==tm[l][k+1])
                                return false;
                        }
                        hoge = true;
                    }
                }
                if(hoge == 0)
                    return false;
            }
        }
    }
    return true;
}

lint dfs(int d){
    lint ans = INF;
    if(d==n){
        if(check()){
//            show();
            return rettm();
        }else{
            return 7e10;
        }
    }
    rep(i,n){
        if(flag[i]==1)
            continue;
        flag[i]=1;
        if(i==0){
            tm[i][0]=0;
            maketm(i);
            ans = min(dfs(d+1),ans);
        }else if(flag[i-1]==1){
            tm[i][0]=tm[i-1][0]+1;
            maketm(i);
            ans = min(dfs(d+1),ans);
        }
        rep(j,n){
            if(j==i||flag[j]==0)
                continue;
            rep(k,m){
                tm[i][0]=tm[j][k+1]-D[k]*S[i];
                maketm(i);
                ans = min(dfs(d+1),ans);
            }
            tm[i][0]=tm[j][m+1]-dist*S[i];
            maketm(i);
            ans = min(dfs(d+1),ans);
        }
        flag[i]=0;
    }
    return ans;
}
    
int main() {
    cin >> dist >> n;
    rep(i,n){
        cin >> S[i];
    }
    cin >> m;
    rep(i,m){
        cin >> D[i];
    }
    cout << dfs(0) << endl;
    return 0;
}
#endif
accuracy: 1
time_ms: 10
memory_kb: 1172
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <bitset>
using namespace std;

typedef long long LL;

LL dist, ans = (LL)1e18;
int n, m;
vector<int> S, intr;
vector<LL> D;

vector<int> ptn;

void enumpattern(int a, int i){
	if(i >= n - 1){
		ptn.push_back(a);
	}
	else{
		enumpattern(a, i + 1);
		enumpattern(a | 1 << i, i + 2);
	}
}


void calcans(){
	vector<LL> stm(n + 1, -1LL);
	LL lst0 = -1, lft0 = 0;	// last start/finish time

	vector<vector<int> > odr(m + 1, vector<int>(n));
	for(int i = 0; i < n; ++i){
		odr[0][i] = i;
	}
	
	int cnt = 0;
	for(int j = 0; j < m; ++j){
		odr[j + 1] = odr[j];
		for(int i = 0; i < n; ++i){
			if(intr[j] >> i & 1){
				++cnt;
				int a = odr[j][i], b = odr[j][i + 1];
				if(a > b || S[a] <= S[b]){
					return;
				}
				swap(odr[j + 1][i], odr[j + 1][i + 1]);
				++i;
			}
		}
	}

	for(int i = 0; i < n; ++i){
		if(stm[i] != -1LL) continue;

		stm[i] = 0;
		bool updated = true;
		while(updated){
			updated = false;

			for(int j = 0; j < m; ++j){
				for(int k = i; k < n; ++k){
					if((intr[j] >> k & 1) == 0){
						continue;
					}

					int a = odr[j][k], b = odr[j][k+1];
					if(stm[a] == -1LL && stm[b] != -1LL){
						updated = true;
						stm[a] = stm[b] + D[j] * (S[b] - S[a]);
					}
					else if(stm[a] != -1LL && stm[b] == -1LL){
						updated = true;
						stm[b] = stm[a] + D[j] * (S[a] - S[b]);
					}
				}
			}
		}

		for(int j = i; stm[j] != -1LL; ++j)
		for(int k = j + 1; stm[k] != -1LL; ++k){
			if(S[j] <= S[k]){ continue; }
			LL ip = (stm[k] - stm[j]) / (S[j] - S[k]);
			if(ip < 0 || ip >= dist){ continue; }
			if((stm[k] - stm[j]) % (S[j] - S[k]) != 0){
				return;
			}
			
			int x = find(D.begin(), D.end(), ip) - D.begin();
			if(x >= m) return;
			int y = find(odr[x].begin(), odr[x].end(), j) - odr[x].begin();
			if(y >= n - 1 || odr[x][y+1] != k ||
			  odr[x+1][y] != k || odr[x+1][y+1] != j){
				return;
			}
			--cnt;
		}
		
		int u = find(stm.begin(), stm.end(), -1LL) - stm.begin() - 1;	//[i,u]
		int farv = odr[m][i], larv = odr[m][u];	//first/last arrival
		LL lst1 = stm[u];
		LL fft1 = S[farv] * dist + stm[farv];
		LL lft1 = S[larv] * dist + stm[larv];

		for(int j = i; j < u; ++j){
			if(stm[j] >= stm[j + 1]){ return; }
		}

		LL offset;
		if(lst0 + fft1 + 1 >= lft0){	//start as early as possible
			offset = lst0 + 1;
		}
		else{
			offset = lft0 - fft1;
		}
		lst0 = offset + lst1;
		lft0 = offset + lft1;

		i = u;
	}
	if(cnt != 0) return;

	ans = min(ans, lft0);
}

void solve(int i){
	if(i == m){
		calcans();
	}
	else{
		for(int j = 0; j < ptn.size(); ++j){
			intr[i] = ptn[j];
			solve(i + 1);
		}
	}
}


int main(){
	cin >> dist >> n;
	S.resize(n);

	for(int i = 0; i < n; ++i){
		cin >> S[i];
	}
	cin >> m;
	D.resize(m);
	intr.resize(m);
	for(int i = 0; i < m; ++i){
		cin >> D[i];
	}
	sort(D.begin(), D.end());

	enumpattern(0, 0);

	solve(0);

	cout << ans << '\n';
}
accuracy: 1
time_ms: 10
memory_kb: 1228
final_rank: 4

code_snippet: #include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <map>
using namespace std;

#define rep(i, n) for(int i = 0; i< (int)(n); i++)
#define all(c) (c).begin(), (c).end()

typedef long long ll;
typedef pair<ll, ll> P;
const ll INF = (ll)1e12;

ll dist, n, m;
ll S[10], D[10], T[10];

bool check(int N, int *p){
  //出発順が守られているか
  vector<P> v;
  rep(i, N + 1) v.push_back(P(p[i], T[i]));
  sort(v.begin(), v.end());
  rep(i, v.size() - 1) if(v[i+1].second <= v[i].second) return false;
  
  //少し広いところを同時に3つ以上の馬車が通るか
  rep(i, m){
    map<int, int> mp;
    rep(j, N + 1) if(++mp[T[j] + D[i] * S[p[j]]] > 2) return false;
  }
  //狭いところですれ違うか
  rep(i, N + 1)rep(j, N){
    bool f = false;
    rep(k, m)   if(T[i] + S[p[i]] * D[k] == T[j] + S[p[j]] * D[k]) f = true;
    if(f) continue;
    if((T[i] - T[j]) * (T[i] - T[j] + (S[p[i]] - S[p[j]]) * dist) < 0) return false; 
  }
  
  return true;
}

ll dfs(int N, int *p){
  ll res = INF;
  if(N == n){
    res = -INF;
    rep(i, n) res = max(res, T[i] + S[p[i]] * dist);
    //cout << res << "  "<< *min_element(T, T + n) << endl;
    return res - *min_element(T, T + n);
  }

  //どの馬車ともすれ違わない場合と
  ll lb = -INF;
  ll ub = INF;
  rep(i, N){
    if(p[i] < p[N]){
      lb = max(lb, T[i] + 1);
      lb = max(lb, (T[i] + (S[p[i]] - S[p[N]]) * dist));
    }else{
      ub = min(ub, T[i] - 1);
      ub = min(ub, (T[i] + (S[p[i]] - S[p[N]]) * dist));
    }
  }
  if(lb <= ub){
    T[N] = lb == -INF ? ub : lb;
    res = min(res, dfs(N + 1, p));
  }
  
  //各少し広いところで各でどの馬車とすれ違うかで探索
  rep(i, m)rep(j, N){
    T[N] = T[j] + (S[p[j]] - S[p[N]]) * D[i];
    if(check(N, p))  res = min(res, dfs(N + 1, p));
  }
  return res;
}

int main(){
  ll res = INF;
  int p[10];
  cin >> dist >> n;
  rep(i, n) cin >> S[i];
  cin >> m;
  rep(i, m) cin >> D[i];
  rep(i, n) p[i] = i;
  do{
    T[0] = 0;
    res = min(res, dfs(1, p));
  }while(next_permutation(p, p + n));
  cout << res << endl;
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1196
final_rank: 3