Problem:
問題 6: 小籠包 (Xiao Long Bao)
問題
JOI 君はお昼ごはんに，中華料理屋で小籠包を食べることにした．
小籠包とは，具と熱いスープを小麦粉の皮で包んだ料理であり，食べるときにスープが周囲に飛び散ることで知られている．
JOI 君が注文した小籠包のセットは，具やスープの異なる N 個の小籠包からなる．
N 個の小籠包は等間隔に一列に並んでおり，順番に 1 から N の番号がつけられている．
 i 番目の小籠包と j 番目の小籠包の間の距離は絶対値 |i - j| である．
JOI 君は小籠包をある順番で食べていく．
最初，すべての小籠包のおいしさは 0 である．
 i 番目の小籠包を食べると，周囲にその汁が飛び散り，まだ食べられていない小籠包のうち，小籠包 i からの距離が D
i
以下の小籠包に汁がかかる．汁がかかった小籠包はおいしさが
 A
i
増える．すなわち， i 番目の小籠包を食べたときに，
 j 番目の小籠包 (1 ≤ j ≤ N かつ i - D
i
≤ j ≤ i + D
i
) がまだ食べられずに残っているならば，
 j 番目の小籠包のおいしさが A
i
増える．
JOI 君は，食べる順番を工夫することで，食べる小籠包のおいしさの合計を最大化したい．
もっとも良い順番で食べたときの，JOI 君が食べる小籠包のおいしさの合計を求めるプログラムを作成せよ．
入力
入力ファイルは 3 行からなる．
1 行目には 1 つの整数 N (1 ≤ N ≤ 100) が書かれている．
2 行目には， N 個の整数 D
1
, D
2
, ..., D
N
(0 ≤ D
i
≤ 7) が空白を区切りとして書かれている．
3 行目には， N 個の整数 A
1
, A
2
, ..., A
N
(0 ≤ A
i
≤ 1000) が空白を区切りとして書かれている．
出力
JOI 君が食べる小籠包のおいしさの合計の最大値を 1 行で出力せよ．
入出力例
入力例 1
5
1 0 1 1 2
0 2 6 3 4
出力例 1
20
入出力例 1 では，5 番目 → 3 番目 → 1 番目 → 2 番目 → 4 番目 の順番で食べると，
おいしさの合計が 20 になる．合計が 20 を超えるような食べ方は存在しないので，これが最善である．
入力例 2
10
5 2 7 2 6 5 3 5 3 6
8 7 8 4 0 6 0 10 10 0
出力例 2
237
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

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

int main() {
    int n;
    cin >> n;

    vector<int> d(n), a(n);
    for (int i = 0; i < n; i++) cin >> d[i];
    for (int i = 0; i < n; i++) cin >> a[i];

    vector<int> base = {0, 1, 2, 3, 4, 5, 6};
    vector<vector<int>> permutations;

    do {
        permutations.push_back(base);
    } while (next_permutation(base.begin(), base.end()));

    int states_count = permutations.size();
    vector<vector<int>> transitions(states_count, vector<int>(8));

    for (int i = 0; i < states_count; i++) {
        for (int j = 0; j < 8; j++) {
            vector<int> modified = permutations[i];
            for (int k = 0; k < 7; k++) {
                if (modified[k] >= j) modified[k]++;
            }

            vector<int> new_state;
            for (int k = 1; k < 8; k++) {
                int val = modified[k];
                if (val > modified[0]) val--;
                new_state.push_back(val);
            }

            auto it = lower_bound(permutations.begin(), permutations.end(), new_state);
            transitions[i][j] = distance(permutations.begin(), it);
        }
    }

    vector<vector<int>> dp(n + 1, vector<int>(states_count, 0));
    int result = 0;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < states_count; j++) {
            vector<int> position_map(8);
            for (int k = 0; k < 7; k++) {
                position_map[permutations[j][k]] = k;
            }

            int current_value = dp[i][j];
            for (int k = 0; k < 7; k++) {
                if (i - 7 + k >= 0 && 7 - k <= d[i]) {
                    current_value += a[i];
                }
            }

            for (int k = 0; k < 8; k++) {
                int next_state = transitions[j][k];
                int new_value = current_value;

                dp[i + 1][next_state] = max(dp[i + 1][next_state], new_value);
                result = max(result, dp[i + 1][next_state]);

                if (i - 7 + position_map[k] >= 0 && 7 - position_map[k] <= d[i]) {
                    current_value -= a[i];
                }
                if (i - 7 + position_map[k] >= 0 && 7 - position_map[k] <= d[i - 7 + position_map[k]]) {
                    current_value += a[i - 7 + position_map[k]];
                }
            }
        }
    }

    cout << result << endl;
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 5620
final_rank: 2

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

int n;
int d[101], a[101];
int dp[101][6000];
int data_table[6000][8];
vector<vector<int>> orders;

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &d[i]);
    for (int i = 0; i < n; i++) scanf("%d", &a[i]);
    
    vector<int> init = {0, 1, 2, 3, 4, 5, 6};
    do {
        orders.push_back(init);
    } while (next_permutation(init.begin(), init.end()));
    
    int total_orders = orders.size();
    for (int i = 0; i < total_orders; i++) {
        for (int j = 0; j < 8; j++) {
            vector<int> temp = orders[i];
            for (int k = 0; k < 7; k++) {
                if (temp[k] >= j) temp[k]++;
            }
            vector<int> new_order;
            for (int k = 1; k < 8; k++) {
                new_order.push_back(temp[k]);
                if (new_order.back() > temp[0]) new_order.back()--;
            }
            auto it = lower_bound(orders.begin(), orders.end(), new_order);
            data_table[i][j] = it - orders.begin();
        }
    }
    
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < total_orders; j++) {
            int pos_map[8];
            for (int k = 0; k < 7; k++) {
                pos_map[orders[j][k]] = k;
            }
            
            int res = dp[i][j];
            for (int k = 0; k < 7; k++) {
                if (i - 7 + k >= 0 && 7 - k <= d[i]) {
                    res += a[i];
                }
            }
            
            for (int k = 0; k < 8; k++) {
                int next_state = data_table[j][k];
                dp[i+1][next_state] = max(dp[i+1][next_state], res);
                ans = max(ans, dp[i+1][next_state]);
                
                if (i - 7 + pos_map[k] >= 0 && 7 - pos_map[k] <= d[i]) {
                    res -= a[i];
                }
                if (i - 7 + pos_map[k] >= 0 && 7 - pos_map[k] <= d[i - 7 + pos_map[k]]) {
                    res += a[i - 7 + pos_map[k]];
                }
            }
        }
    }
    
    printf("%d\n", ans);
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 5604
final_rank: 1

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Info{
	int range,add;
};

int N;
int table_index,max_digit;
int num_array[7],xiao[7],work[8],order[7],calc[7];
int table[5040][7];
int dp[100][5040];
bool used[7];
Info info[100];
map<int,int>MAP;

//num_arrayとusedはグローバルに持つ
void makeTable(int index){

	if(index == max_digit){
		int tmp = 0;
		for(int i = 0; i < max_digit; i++){
			table[table_index][i] = num_array[i];
			tmp = 10*tmp+num_array[i];
		}
		MAP[tmp] = table_index;
		table_index++;
		return;
	}
	for(int i = 0; i < max_digit; i++){
		if(used[i] == false){
			num_array[index] = i;
			used[i] = true;
			makeTable(index+1);
			used[i] = false;
		}
	}
}

int main(){

	scanf("%d",&N);

	for(int i = 0; i < N; i++){
		scanf("%d",&info[i].range);
	}
	for(int i = 0; i < N; i++){
		scanf("%d",&info[i].add);
	}

	//順列テーブルを作成する
	table_index = 0;
	max_digit = min(7,N);

	for(int i = 0; i < max_digit; i++)used[i] = false;
	makeTable(0);

	for(int i = 0; i < N; i++){
		for(int state = 0; state < table_index; state++)dp[i][state] = 0;
	}

	int next_state,next_value,index,tmp_num;

	//左端の計算
	for(int state = 0; state < table_index; state++){

		for(int k = 0; k < max_digit; k++)order[k] = table[state][k]; //順番の取得
		//小籠包を順番に並べる
		for(int a = 0; a < max_digit; a++){
			work[a] = order[a];
		}
		next_value = 0;
		for(int a = 0; a < max_digit-1; a++){ //汁を飛び散らせる小籠包のループ
			for(int b = a+1; b < max_digit; b++){ //汁を浴びる小籠包のループ
				if(abs(work[a]-work[b]) <= info[work[a]].range){
					next_value += info[work[a]].add;
				}
			}
		}
		dp[max_digit-1][state] = next_value;
		if(next_value == 0){
			printf("state:%d\n",state);
		}
	}

	if(N <= 7){

		int ans = 0;
		for(int state = 0; state < table_index; state++){
			ans = max(ans,dp[max_digit-1][state]);
		}

		printf("%d\n",ans);

		return 0;
	}

	for(int loc = 7; loc <= N-1; loc++){

		for(int k = 0; k < 7; k++)xiao[k] = loc-(7-k); //作業量配列で扱う小籠包のインデックス

		for(int state = 0; state < 5040; state++){ //左7個の状態の走査

			for(int k = 0; k < 7; k++)order[k] = table[state][k]; //順番の取得

			//★locの小籠包の、相対順位のループ
			for(int pos = 0; pos <= 7; pos++){
				//小籠包を順番に並べる
				for(int a = 0; a <= 7; a++)work[a] = -1;
				work[pos] = loc;
				index = 0;
				for(int a = 0; a <= 7; a++){
					if(work[a] == -1){
						work[a] = xiao[order[index++]];
					}
				}
				//おいしさの増加分を計算
				next_value = dp[loc-1][state];

				//locの増加分(locより前に食べられた小籠包で、汁がlocにかかるものを求める)
				for(int a = 0; a < pos; a++){
					if(abs(work[a]-loc) <= info[work[a]].range){
						next_value += info[work[a]].add;
					}
				}
				//locの汁が飛び散ることによる増加分
				for(int a = pos+1; a <= 7; a++){
					if(abs(work[a]-loc) <= info[loc].range){
						next_value += info[loc].add;
					}
				}

				//新しい状態を計算する(loc-7の小籠包を除いた順位を計算する)
				index = 0;

				for(int a = 0; a <= 7; a++){
					if(work[a] == loc-7)continue;
					calc[index++] = 6-(loc-work[a]);
				}
				tmp_num = 0;
				for(int i = 0; i < 7; i++)tmp_num = 10*tmp_num+calc[i];

				next_state = MAP[tmp_num];

				dp[loc][next_state] = max(dp[loc][next_state],next_value);
			}
		}
	}

	int ans = 0;
	for(int state = 0; state < 5040; state++){
		ans = max(ans,dp[N-1][state]);
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 5656
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(A) A.begin(),A.end()
int main(){
    int N;cin>>N;
    vector<int>P={0,1,2,3,4,5,6},A(N),D(N);
    vector<vector<int>>perm;
    do{
        perm.emplace_back(P);
    }while(next_permutation(ALL(P)));
    for(int i=0;i<N;i++)cin>>D[i];
    for(int i=0;i<N;i++)cin>>A[i];
    vector<vector<int>>DP(N,vector<int>(5040));
    FOR(i,1,N)REP(j,5040){
        REP(k,8){
            auto P=perm[j];
            int score=DP[i-1][j];
            for(int l=0;l<k;l++)if(i-1-P[l]>=0&&D[i-1-P[l]]>=1+P[l])score+=A[i-1-P[l]];
            for(int l=k;l<7;l++)if(i-1-P[l]>=0&&1+P[l]<=D[i])score+=A[i];
            P.insert(P.begin()+k,-1);
            P.erase(find(ALL(P),6));
            for(auto&c:P)c++;
            int t=lower_bound(ALL(perm),P)-perm.begin();
            DP[i][t]=max(DP[i][t],score);
        }
    }
    cout<<*max_element(ALL(DP[N-1]))<<endl;
    return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 5452
final_rank: 6

code_snippet: #include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<unordered_map>
#include<stack>
#include<string>
#include<algorithm>
#include<functional>
#include<cstring>
#include<complex>
#include<bitset>
#include<iostream>
#include<cassert>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef pair<ll, P> Q;
typedef complex<double> C;
#define cx real()
#define cy imag()
const ll INF = 1LL << 60;
const double DINF = 1e30;
const ll mod = 1000000007;
const ll dx[4] = {1, 0, -1, 0};
const ll dy[4] = {0, -1, 0, 1};
const C I = C(0, 1);
const double EPS = 1e-10;
const ll NCK_MAX = 510000;

ll gcd(ll a, ll b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

ll extgcd(ll a, ll b, ll& x, ll& y) {
  if (b == 0) {
    x = 1, y = 0; return a;
  }
  ll q = a/b, g = extgcd(b, a - q*b, x, y);
  ll z = x - q * y;
  x = y;
  y = z;
  return g;
}

ll invmod (ll a, ll m) { // a^-1 mod m
  ll x, y;
  extgcd(a, m, x, y);
  x %= m;
  if (x < 0) x += m;
  return x;
}

ll *fac, *finv, *inv;

void nCk_init(ll mod) {
  fac = new ll[NCK_MAX];
  finv = new ll[NCK_MAX];
  inv = new ll[NCK_MAX];
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for (ll i = 2; i < NCK_MAX; i++) {
    fac[i] = fac[i-1] * i % mod;
    inv[i] = mod - inv[mod%i] * (mod / i) % mod;
    finv[i] = finv[i-1] * inv[i] % mod;
  }
}

ll nCk(ll n, ll k, ll mod) {
  if (fac == NULL) nCk_init(mod);
  if (n < k) return 0;
  if (n < 0 || k < 0) return 0;
  return fac[n] * (finv[k] * finv[n-k] % mod) % mod;
}

template <typename T>
class Zip {
  vector<T> d;
  bool flag;
  void init() {
    sort(d.begin(), d.end());
    d.erase(unique(d.begin(), d.end()), d.end());
    flag = false;
  }
public:
  Zip() {
    flag = false;
  }
  void add(T x) {
    d.push_back(x);
    flag = true;
  }
  ll getNum(T x) {
    if (flag) init();
    return lower_bound(d.begin(), d.end(), x) - d.begin();
  }
  ll size() {
    if (flag) init();
    return (ll)d.size();
  }
};

class UnionFind {
  vector<ll> par, rank; // par > 0: number, par < 0: -par
public:
  UnionFind(ll n) : par(n, 1), rank(n, 0) {}
  ll getSize(ll x) {
    return par[find(x)];
  }
  ll find(ll x) {
    if (par[x] > 0) return x;
    return -(par[x] = -find(-par[x]));
  }
  void merge(ll x, ll y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      par[y] += par[x];
      par[x] = -y;
    } else {
      par[x] += par[y];
      par[y] = -x;
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool isSame(ll x, ll y) {
    return find(x) == find(y);
  }
};


template <typename T>
class SegmentTree {
  ll n;
  vector<T> node;
  function<T(T, T)> fun, fun2;
  bool customChange;
  T outValue, initValue;
public:
  void init(ll num, function<T(T, T)> resultFunction, T init, T out, function<T(T, T)> changeFunction = NULL) {
    // changeFunction: (input, beforevalue) => newvalue
    fun = resultFunction;
    fun2 = changeFunction;
    customChange = changeFunction != NULL;
    n = 1;
    while (n < num) n *= 2;
    node.resize(2 * n - 1);
    fill(node.begin(), node.end(), init);
    outValue = out;
    initValue = init;
  }
  void valueChange(ll num, T value) {
    num += n-1;
    if (customChange) node[num] = fun2(value, node[num]);
    else node[num] = value;
    while (num > 0) num = (num - 1) / 2, node[num] = fun(node[num * 2 + 1], node[num * 2 + 2]);
  }
  T rangeQuery(ll a, ll b, ll l = 0, ll r = -1, ll k = 0) { // [a, b)
    if (r == -1) r = n;
    if (a <= l && r <= b) return node[k];
    if (b <= l || r <= a) return outValue;
    ll mid = (l + r) / 2;
    return fun(rangeQuery(a, b, l, mid, 2*k+1), rangeQuery(a, b, mid, r, 2*k+2));
  }
};

template <typename T>
class Graph {
  struct edge { ll to; T cost; };
  struct edge_data { ll from, to; T cost; };

  ll v;
  vector<vector<edge>> e, re;
  vector<edge_data> ed;
  vector<bool> used;
  vector<ll> vs, cmp;
  bool isDirected, isMinasEdge;
public:
  Graph(ll _v, bool _isDirected = true, ll range_add = 0) {
    // range_add 0:no / 1:in / 2:out / 3:in+out
    //_v++;
    v = _v, isDirected = _isDirected; isMinasEdge = false;
    e.resize(v), re.resize(v);
  }
  void add_edge(ll s, ll t, T cost = 1) {
    e[s].push_back((edge){t, cost});
    if (!isDirected) e[t].push_back((edge){s, cost});
    else re[t].push_back((edge){s, cost});
    ed.push_back((edge_data){s, t, cost});
    if (cost < 0) isMinasEdge = true;
  }
  vector<T> dijkstra(ll s) {
    vector<T> d(v, INF);
    d[s] = 0;
    auto edge_cmp = [](const edge& a, const edge& b) { return a.cost > b.cost; };
    priority_queue<edge, vector<edge>, decltype(edge_cmp)> pq(edge_cmp);
    pq.push((edge){s, 0});
    while (!pq.empty()) {
      edge temp = pq.top(); pq.pop();
      if (d[temp.to] < temp.cost) continue;
      for (const edge& next : e[temp.to]) {
        T cost = temp.cost + next.cost;
        if (d[next.to] > cost) {
          d[next.to] = cost;
          pq.push((edge){next.to, cost});
        }
      }
    }
    return d;
  }
  vector<T> bellmanford(ll s) {
    vector<T> d(v, INF);
    d[s] = 0;
    for (ll i = 0; i < v; i++) {
      for (const edge_data& temp : ed) {
        if (d[temp.from] != INF && d[temp.to] > d[temp.from] + temp.cost) d[temp.to] = d[temp.from] + temp.cost;
        if (!isDirected && d[temp.to] != INF && d[temp.from] > d[temp.to] + temp.cost) d[temp.from] = d[temp.to] + temp.cost;
      }
    }
    for (ll i = 0; i < v; i++) {
      for (const edge_data& temp : ed) {
        if (d[temp.from] != INF && d[temp.to] > d[temp.from] + temp.cost) d[temp.to] = -INF;
        if (!isDirected && d[temp.to] != INF && d[temp.from] > d[temp.to] + temp.cost) d[temp.from] = -INF;
      }
    }
    return d;
  }
  vector<T> shortest_path(ll s) {
    if (isMinasEdge) return bellmanford(s);
    else return dijkstra(s);
  }
  T kruskal() {
    // if (isDirected)
    UnionFind uf(v);
    auto edge_data_cmp = [](const edge_data& a, const edge_data& b) { return a.cost < b.cost; };
    sort(ed.begin(), ed.end(), edge_data_cmp);
    T ans = 0;
    for (const edge_data& temp : ed) {
      if (uf.isSame(temp.from, temp.to)) continue;
      uf.merge(temp.from, temp.to);
      ans += temp.cost;
    }
    return ans;
  }
  void scc_dfs(ll s) {
    used[s] = true;
    for (const edge& i : e[s]) if (!used[i.to]) scc_dfs(i.to);
    vs.push_back(s);
  }
  void scc_rdfs(ll s, ll k) {
    used[s] = true;
    cmp[s] = k;
    for (const edge& i : re[s]) if (!used[i.to]) scc_rdfs(i.to, k);
  }
  vector<ll> scc() {
    used.resize(v);
    fill(used.begin(), used.end(), false);
    cmp.resize(v);
    vs.clear();
    for (ll i = 0; i < v; i++) if (!used[i]) scc_dfs(i);
    used.resize(v);
    fill(used.begin(), used.end(), false);
    ll k = 0;
    for (ll i = vs.size() - 1; i >= 0; i--) if (!used[vs[i]]) scc_rdfs(vs[i], k++);
    return cmp;
  }
};

class RollingHash {
  int base;
  vector<__int128> hash;
  vector<__int128> pw;
  const __int128 hashmod = (1ull << 61) - 1;
public:
  RollingHash(string s, int base = 10007) : base(base), hash(s.length()+1, 0), pw(s.length()+1, 1) {
    for (int i = 0; i < (int)s.length(); i++) {
      hash[i+1] = (hash[i] * base + s[i]) % hashmod;
      pw[i+1] = pw[i] * base % hashmod;
    }
  }
  ll get(ll a, ll b) { // [a, b)
    __int128 tmp = hashmod + hash[b] - hash[a] * pw[b-a] % hashmod;
    if (tmp >= hashmod) tmp -= hashmod;
    return (ll)tmp;
  }
};

ll n, d[100], a[100];

ll conv_v_to_ll(vector<ll>& v) {
  ll res = 0;
  for (ll i : v) res = 10 * res + i;
  return res;
}
vector<ll> conv_ll_to_v(ll x, ll len) {
  vector<ll> res;
  for (ll i = 0; i < len; i++) res.push_back(x % 10), x /= 10;
  reverse(res.begin(), res.end());
  return res;
}
vector<ll> backup1(10), backup2(10), backup3(10);

int main() {
  scanf("%lld", &n);
  for (ll i = 0; i < n; i++) scanf("%lld", &d[i]);
  for (ll i = 0; i < n; i++) scanf("%lld", &a[i]);
  map<ll, ll> m;
  m[0] = 0;
  // [3, 2, 5, 4, 1, 6, 0] 高々7個前までの順番(0-indexed)
  for (ll i = 0; i < n; i++) {
    map<ll, ll> new_m;
    for (auto it = m.begin(); it != m.end(); it++) {
      // 今見ているものをborder番目に食べる(もともとborder以上+1)
      vector<ll> tmp = conv_ll_to_v(it->first, min(7LL, i));
      for (ll border = 0; border <= tmp.size(); border++) {
        ll old_cost = it->second;
        vector<ll> old(tmp.size());
        copy(tmp.begin(), tmp.end(), old.begin());
        for (ll k = 0; k < old.size(); k++) {
          ll minas = old.size() - k;
          if (old[k] >= border) {
            old[k]++;
            if (d[i] >= minas) { // iを先に食べるので汁がかかるか
              old_cost += a[i];
            }
          } else {
            if (d[i-minas] >= minas) { // kを先に食べるので汁がかかるか
              old_cost += a[i-minas];
            }
          }
        }
        copy(old.begin(), old.end(), backup1.begin());
        if (old.size() == 7) {
          ll first = old[0];
          for (ll i = 0; i < (ll)old.size()-1; i++) {
            swap(old[i], old[i+1]);
          }
          old[6] = border;
          for (ll i = 0; i < (ll)old.size(); i++) if (old[i] >= first) old[i]--;
        } else {
          old.push_back(border);
        }
        ll new_key = conv_v_to_ll(old);
        new_m[new_key] = max(new_m[new_key], old_cost);
        /*
        printf("%lld: ", i);
        for (ll l : old) printf("%lld ", l);
        printf("-> %lld\n", old_cost);
        fflush(stdout);
        */
        /*
        for (ll i = 0; i < old.size(); i++) if (i < 0 or 7 < i) printf("Error1\n");
        sort(old.begin(), old.end());
        for (ll i = 0; i < old.size()-1; i++) if (old[i] == old[i+1]) {
          printf("Error2\n");
          for (ll x : tmp) printf("%lld ", x); printf("\n");
          printf("+%lld\n", border);
          for (ll x : backup1) printf("%lld ", x); printf("\n");
          for (ll x : old) printf("%lld ", x); printf("\n");
          exit(0);
        }
        if (old.size() > 7) printf("Error3\n");
        */
      }
    }
    swap(new_m, m);
  }
  ll ans = 0;
  for (auto it = m.begin(); it != m.end(); it++) ans = max(ans, it->second);
  printf("%lld\n", ans);
}
accuracy: 1
time_ms: 520
memory_kb: 4124
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=998244353;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}


void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int N,M=5040,S=7;
	cin>>N;
	vector<int> D(N),A(N);
	rep(i,N) cin>>D[i];
	rep(i,N) cin>>A[i];
	vector<vector<int>> dp(N+1,vector<int>(M));
	vector<vector<int>> table(M,vector<int>(S));
	rep(i,7) table[0][i]=i;
	rep(i,M-1) table[i+1]=table[i],next_permutation(all(table[i+1]));
	auto f=[&](vector<int> &p)->int{
		vector<int> use(S);
		int X=M,ans=0;
		rep(i,S){
			X/=(S-i);
			rep(j,p[i]) if(use[j]==0) ans+=X;
			use[p[i]]=1;
		}
		return ans;
	};
	rep(i,N) rep(j,M){
		rep(k,S+1){
			vector<int> n_order;
			int ind,tmp=dp[i][j];
			rep(l,k){
				ind=i-1-table[j][l];
				if(ind>=0&&D[ind]+ind>=i) tmp+=A[ind];
				if(table[j][l]!=S-1) n_order.push_back(table[j][l]+1);
			}
			n_order.push_back(0);
			for(int l=k;l<S;l++){
				ind=i-1-table[j][l];
				if(ind>=0&&ind>=i-D[i]) tmp+=A[i];
				if(table[j][l]!=S-1) n_order.push_back(table[j][l]+1);
			}
			chmax(dp[i+1][f(n_order)],tmp);
		}
	}
	int ans=0;
	rep(i,M) chmax(ans,dp[N][i]);
	cout<<ans<<"\n";
}
accuracy: 1
time_ms: 670
memory_kb: 5728
final_rank: 9

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
#ifdef noimi
#pragma GCC optimize("unroll-loops")
#endif
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")

#include <immintrin.h>

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfenv>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <streambuf>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#define endl '\n'
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define fore(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
const string firstsecond[2] = {"second", "first"};
const string FirstSecond[2] = {"Second", "First"};
const string possiblestr[2] = {"impossible", "possible"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
void first(bool t = 1) { cout << firstsecond[t] << endl; }
void First(bool t = 1) { cout << FirstSecond[t] << endl; }
void possible(bool t = 1) { cout << possiblestr[t] << endl; }

template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef noimi
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#ifdef noimi
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(11);
    }
} setup_io;

constexpr int oj_local(int oj, int local) {
#ifdef noimi
    return local;
#endif
    return oj;
}
constexpr bool is_local = oj_local(0, 1);

#pragma endregion

constexpr int m = 7;
int ptoi(const vi &v) {
    int b = 0, res = 0;
    rep3(i, si(v) - 1, 0) {
        res = res * (m - i) + popcount(b & allbit(v[i]));
        b ^= 1 << v[i];
    }
    return res;
}

constexpr int M() {
    int res = 1;
    rep2(i, 1, m) res *= i;
    return res;
}

int main() {
    INT(n);
    VEC(int, d, n);
    VEC(int, a, n);

    vv(int, ps, M());
    {
        auto id = iota(m);
        do { ps[ptoi(id)] = id; } while(next_permutation(all(id)));
    }

    if(n <= m) {
        int ma = 0;
        auto id = iota(n);
        do {
            int tmp = 0;
            rep(i, n) rep(j, n) {
                if(id[i] < id[j] and abs(i - j) <= d[i]) tmp += a[i];
            }
            chmax(ma, tmp);
        } while(next_permutation(all(id)));
        OUT(ma);
    } else {
        vv(int, dp, n + 1, M());
        {
            int i = 0;
            fore(id, ps) {
                int tmp = 0;
                rep(i, m) rep(j, m) {
                    if(id[i] < id[j] and abs(i - j) <= d[i]) tmp += a[i];
                }
                dp[m][i++] = tmp;
            }
        }

        rep2(i, m, n - 1) {
            rep(j, si(ps)) {
                auto &v = ps[j];
                int tmp = dp[i][j];
                vi nxt(m);
                rep(k, m + 1) {
                    int now = tmp;
                    rep(s, m) {
                        if(v[s] < k and (m - s) <= d[i - m + s])
                            now += a[i - m + s];
                        else if(v[s] >= k and (m - s) <= d[i])
                            now += a[i];
                    }
                    int l = v[0];
                    rep2(s, 1, m - 1) {
                        int to = v[s];
                        if(v[s] >= k) to++;
                        if(v[s] > l) to--;
                        nxt[s - 1] = to;
                    }
                    nxt[m - 1] = (k - (k > l));
                    chmax(dp[i + 1][ptoi(nxt)], now);
                }
            }
        }
        OUT(MAX(dp[n]));
    }
}

// 1 4 6 5 2 3 0
accuracy: 1
time_ms: 120
memory_kb: 5360
final_rank: 4

code_snippet: #include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main() {
	int N;
	cin >> N;
	vector<int> D(N), A(N);
	for (int i = 0; i < N; ++i) cin >> D[i];
	for (int i = 0; i < N; ++i) cin >> A[i];
	vector<vector<int> > perm;
	int md = *max_element(D.begin(), D.end());
	vector<int> p(md);
	for (int i = 0; i < md; ++i) {
		p[i] = i;
	}
	do {
		perm.push_back(p);
	} while (next_permutation(p.begin(), p.end()));
	function<int(vector<int>)> find_index = [&](vector<int> v) {
		vector<int> vp(v.size());
		for (int i = 0; i < v.size(); ++i) {
			for (int j = 0; j < v.size(); ++j) {
				if (v[j] < v[i] || (v[j] == v[i] && j < i)) ++vp[i];
			}
		}
		return lower_bound(perm.begin(), perm.end(), vp) - perm.begin();
	};
	int ps = perm.size();
	vector<int> dp(ps);
	for (int i = 0; i < N; ++i) {
		vector<int> ndp(ps);
		for (int j = 0; j < ps; ++j) {
			vector<int> np = perm[j];
			np.insert(np.begin(), -1);
			np.pop_back();
			for (int k = 0; k <= md; ++k) {
				int delta = 0;
				for (int l = 1; l <= md && l <= i; ++l) {
					if (l <= D[i - l] && perm[j][l - 1] < k) {
						delta += A[i - l];
					}
					if (l <= D[i] && perm[j][l - 1] >= k) {
						delta += A[i];
					}
				}
				np[0] = k;
				int idx = find_index(np);
				ndp[idx] = max(ndp[idx], dp[j] + delta);
			}
		}
		dp = ndp;
	}
	int ans = *max_element(dp.begin(), dp.end());
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1030
memory_kb: 3380
final_rank: 10

code_snippet: #include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <map>

constexpr int INF = 1 << 30;

std::vector<int> facts;
std::map<std::vector<int>, int> encs;
std::vector<std::vector<int>> decs;

void init() {
    facts.resize(9);
    facts[0] = 1;
    for (int i = 1; i <= 8; ++i) facts[i] = facts[i - 1] * i;

    decs.resize(facts[7]);
    std::vector<int> idxs(7);
    std::iota(idxs.begin(), idxs.end(), 0);
    int cnt = 0;
    do {
        decs[cnt] = idxs;
        encs[idxs] = cnt++;
    } while (std::next_permutation(idxs.begin(), idxs.end()));
}

int enc(std::vector<int> xs) {
    while (xs.size() < 7) xs.push_back(xs.size());
    return encs[xs];
}

std::vector<int> compress(const std::vector<int>::iterator& begin,
                          const std::vector<int>::iterator& end) {
    std::vector<int> idxs(begin, end);
    int n = idxs.size();

    std::vector<int> ret(n, 0);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (idxs[i] > idxs[j]) ++ret[i];
        }
    }
    return ret;
}

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> ds(n), xs(n);
    for (auto& d : ds) std::cin >> d;
    for (auto& x : xs) std::cin >> x;

    std::vector<int> dp(facts[7], -INF);
    int r = std::min(7, n);
    // exhaustive search on [0, r)
    {
        std::vector<int> idxs(r);
        std::iota(idxs.begin(), idxs.end(), 0);
        do {
            int sum = 0;

            for (int i = 0; i < r; ++i) {
                for (int j = 0; j < r; ++j) {
                    if (std::abs(i - j) > ds[i] ||
                        idxs[i] >= idxs[j]) continue;
                    sum += xs[i];
                }
            }

            dp[enc(idxs)] = sum;
        } while (std::next_permutation(idxs.begin(), idxs.end()));
    }

    auto ndp = dp;
    std::vector<int> idxs(8);
    std::iota(idxs.begin(), idxs.end(), 0);

    while (r < n) {
        std::fill(ndp.begin(), ndp.end(), -INF);

        do {
            int prev = enc(compress(idxs.begin(), --idxs.end()));
            int nxt = enc(compress(++idxs.begin(), idxs.end()));

            int sum = 0;
            for (int i = 0; i < 7; ++i) {
                int l = r - 7 + i;
                if (idxs[i] < idxs[7] && std::abs(r - l) <= ds[l]) sum += xs[l];
                if (idxs[i] > idxs[7] && std::abs(r - l) <= ds[r]) sum += xs[r];
            }

            ndp[nxt] = std::max(ndp[nxt], sum + dp[prev]);
        } while (std::next_permutation(idxs.begin(), idxs.end()));

        std::swap(dp, ndp);
        ++r;
    }

    std::cout << *std::max_element(dp.begin(), dp.end()) << "\n";
}

int main() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);

    init();
    solve();

    return 0;
}
accuracy: 1
time_ms: 1660
memory_kb: 4204
final_rank: 12

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
template <typename T> using posteriority_queue = priority_queue<T, vector<T>, greater<T> >;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
// const int dy[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
template <typename T> void unique(vector<T> &a) { a.erase(unique(ALL(a)), a.end()); }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

int main() {
  int n; cin >> n;
  vector<int> d(n), a(n);
  REP(i, n) cin >> d[i];
  REP(i, n) cin >> a[i];
  if (n <= 7) {
    vector<int> p(n);
    iota(ALL(p), 0);
    int ans = 0;
    do {
      int xiao = 0;
      vector<int> now(n, 0);
      REP(i, n) {
        xiao += now[p[i]];
        FOR(j, 1, d[p[i]] + 1) {
          if (p[i] + j < n) now[p[i] + j] += a[p[i]];
          if (p[i] - j >= 0) now[p[i] - j] += a[p[i]];
        }
      }
      chmax(ans, xiao);
    } while (next_permutation(ALL(p)));
    cout << ans << '\n';
    return 0;
  }
  map<vector<int>, int> prv;
  vector<int> p(7);
  iota(ALL(p), 0);
  do {
    int xiao = 0;
    vector<int> now(7, 0);
    REP(i, 7) {
      xiao += now[p[i]];
      FOR(j, 1, d[p[i]] + 1) {
        if (p[i] + j < 7) now[p[i] + j] += a[p[i]];
        if (p[i] - j >= 0) now[p[i] - j] += a[p[i]];
      }
    }
    prv[p] = xiao;
  } while (next_permutation(ALL(p)));
  FOR(i, 7, n) {
    map<vector<int>, int> nxt;
    for (auto &pr : prv) {
      const vector<int> &v = pr.first;
      vector<int> enc(v);
      for (int &e : enc) e = i - (7 - e);
      REP(j, 8) {
        int xiao = 0;
        REP(k, j) if (d[enc[k]] >= 7 - v[k]) xiao += a[enc[k]];
        FOR(k, j, 7) if (d[i] >= 7 - v[k]) xiao += a[i];
        vector<int> nx_v(v);
        nx_v.emplace(nx_v.begin() + j, 7);
        nx_v.erase(find(ALL(nx_v), 0));
        for (int &e : nx_v) --e;
        chmax(nxt[nx_v], pr.second + xiao);
      }
    }
    swap(prv, nxt);
  }
  int ans = 0;
  for (auto &pr : prv) chmax(ans, pr.second);
  cout << ans << '\n';
  return 0;
}
accuracy: 1
time_ms: 690
memory_kb: 4492
final_rank: 8

code_snippet: #include"bits/stdc++.h"
using namespace std;
#define LL long long
#define REP(i, n) for(int (i)=0; (i)<(n); (i)++)
#define PB push_back
#define MP make_pair
#define MOD 1000000007

//7!=5040
//N=100

int N;
LL D[100],A[100];

map<pair<int,vector<int>>, vector<int>> dp2;
vector<int> ins(vector<int> v, int p){
	if(dp2.count(MP(p,v)) == 1) return dp2[MP(p,v)];

	//if(v.size() == 7) cout << "look" << endl;
	//for(int k=0; k<v.size(); k++) cout << v[k] << " ";
	//cout << endl;

	vector<int> memo = v;

	v.insert(v.begin()+p, 0);
	for(int i=0; i<v.size(); i++){
		if(v[i] < 7) v[i]++;
		else{
			v.erase(v.begin()+i);
			i--;
		}
	}

	//for(int k=0; k<v.size(); k++) cout << v[k] << " ";
	//cout << endl;

	return dp2[MP(p,memo)] = v;
}

map<pair<int,vector<int>>, LL> dp;
LL solve(int now, vector<int> v){ //v[i]はi番目に食べるもの、値域1～7
	if(now == N) return 0;
	if(dp.count(MP(now,v)) == 1) return dp[MP(now,v)];

	//for(int k=0; k<v.size(); k++) cout << v[k] << " ";
	//cout << endl;

	LL ans = 0;
	for(int i=0; i<v.size()+1; i++){
		LL s = 0;
		for(int j=0; j<i; j++){
			if(D[now-v[j]] >= v[j]){
				s += A[now-v[j]];
			}
		}
		for(int j=i; j<v.size(); j++){
			if(D[now] >= v[j]){
				s += A[now];
			}
		}
		s += solve(now+1, ins(v,i));
		ans = max(ans, s);
	}
	return dp[MP(now,v)] = ans;
}

int main(){
	scanf("%d", &N);
	for(int i=0; i<N; i++) scanf("%lld",D+i);
	for(int i=0; i<N; i++) scanf("%lld",A+i);

	vector<int> v;
	LL ans = solve(0,v);
	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 2720
memory_kb: 70528
final_rank: 17

code_snippet: #include"bits/stdc++.h"
using namespace std;
#define LL long long
#define REP(i, n) for(int (i)=0; (i)<(n); (i)++)
#define PB push_back
#define MP make_pair
#define MOD 1000000007

//7!=5040
//N=100

int N;
LL D[100],A[100];

map<pair<int,vector<int>>, vector<int>> dp2;
vector<int> ins(vector<int> v, int p){
	if(dp2.count(MP(p,v)) == 1) return dp2[MP(p,v)];
	v.insert(v.begin()+p, 0);
	for(int i=0; i<v.size(); i++){
		if(v[i] < 7) v[i]++;
		else{
			v.erase(v.begin()+i);
			i--;
		}
	}
	return dp2[MP(p,v)] = v;
}

map<pair<int,vector<int>>, LL> dp;
LL solve(int now, vector<int> v){ //v[i]はi番目に食べるもの、値域1～7
	if(now == N) return 0;
	if(dp.count(MP(now,v)) == 1) return dp[MP(now,v)];
	LL ans = 0;
	for(int i=0; i<v.size()+1; i++){
		LL s = 0;
		for(int j=0; j<i; j++){
			if(D[now-v[j]] >= v[j]){
				s += A[now-v[j]];
			}
		}
		for(int j=i; j<v.size(); j++){
			if(D[now] >= v[j]){
				s += A[now];
			}
		}
		s += solve(now+1, ins(v,i));
		ans = max(ans, s);
	}
	return dp[MP(now,v)] = ans;
}

int main(){
	scanf("%d", &N);
	for(int i=0; i<N; i++) scanf("%lld",D+i);
	for(int i=0; i<N; i++) scanf("%lld",A+i);

	vector<int> v;
	LL ans = solve(0,v);
	printf("%lld\n",ans);

	return 0;
}
accuracy: 0.2
time_ms: 3070
memory_kb: 64052
final_rank: 20

code_snippet: #define _USE_MATH_DEFINES

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>

using namespace std;

typedef pair<long long int, long long int> P;

long long int INF = 1e18;
long long int MOD = 1e9 + 7;

int main(){
	int N;
	cin >> N;
	int D[110] = {}, A[110] = {};
	for(int i = 0; i < N; i++){
		cin >> D[i];
	}
	for(int i = 0; i < N; i++){
		cin >> A[i];
	}
	int sz = min(7, N);
	int a[8] = {1, 2, 3, 4, 5, 6, 7, 0};
	unordered_map<int, int> m;
	do{
		int S = 0;
		int pos = 0;
		for(int i = 0; i < sz; i++){
			for(int j = i + 1; j < sz; j++){
				if(a[i] > a[j] && j - i <= D[j]){
					S += A[j];
				}else if(a[j] > a[i] && j - i <= D[i]){
					S += A[i];
				}
			}
			pos *= 10;
			pos += a[i];
		}
		m[pos] = S;
	}while(next_permutation(a, a + sz));
	for(int i = 7; i < N; i++){
		unordered_map<int, int> m2;
		for(pair<int, int> p : m){
			//cout << p.first << " " << p.second << endl;
			for(int j = 6; j >= 0; j--){
				a[j] = p.first % 10;
				p.first /= 10;
			}
			for(int j = 0; j < 8; j++){
				int S = p.second;
				for(int k = 0; k < 7; k++){
					if(a[k] > j && 7 - k <= D[i]){
						S += A[i];
					}else if(a[k] <= j && 7 - k <= D[i - (7 - k)]){
						S += A[i - (7 - k)];
					}
				}
				int pos = 0;
				for(int k = 1; k < 7; k++){
					pos += a[k];
					if(a[0] < a[k]){
						pos -= 1;
					}
					if(j < a[k]){
						pos += 1;
					}
					pos *= 10;
				}
				pos += j;
				if(j < a[0]){
					pos += 1;
				}
				m2[pos] = max(m2[pos], S);
				//cout << "m2 " << pos << " " << S << endl;
			}
			//return 0;
		}
		m = m2;
	}
	int ans = 0;
	for(pair<int, int> p : m){
		ans = max(ans, p.second);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 3516
final_rank: 3

code_snippet: #define _USE_MATH_DEFINES

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>

using namespace std;

typedef pair<long long int, long long int> P;

long long int INF = 1e18;
long long int MOD = 1e9 + 7;

int main(){
	int N;
	cin >> N;
	int D[110] = {}, A[110] = {};
	for(int i = 0; i < N; i++){
		cin >> D[i];
	}
	for(int i = 0; i < N; i++){
		cin >> A[i];
	}
	int sz = min(7, N);
	int a[8] = {1, 2, 3, 4, 5, 6, 7, 0};
	unordered_map<int, int> m;
	do{
		int S = 0;
		int pos = 0;
		for(int i = 0; i < sz; i++){
			for(int j = i + 1; j < sz; j++){
				if(a[i] > a[j] && j - i <= D[j]){
					S += A[j];
				}else if(a[j] > a[i] && j - i <= D[i]){
					S += A[i];
				}
			}
			pos *= 10;
			pos += a[i];
		}
		m[pos] = S;
	}while(next_permutation(a, a + sz));
	for(int i = 7; i < N; i++){
		unordered_map<int, int> m2;
		for(pair<int, int> p : m){
			//cout << p.first << " " << p.second << endl;
			for(int j = 6; j >= 0; j--){
				a[j] = p.first % 10;
				p.first /= 10;
			}
			for(int j = 0; j < 8; j++){
				int S = p.second;
				for(int k = 0; k < 7; k++){
					if(a[k] >= j && 7 - k <= D[i]){
						S += A[i];
					}else if(a[k] < j && 7 - k <= D[i - (7 - k)]){
						S += A[i - (7 - k)];
					}
				}
				int pos = 0;
				for(int k = 1; k < 7; k++){
					pos += a[k];
					if(a[0] < a[k]){
						pos -= 1;
					}
					if(j < a[k]){
						pos += 1;
					}
					pos *= 10;
				}
				pos += j;
				if(j < a[0]){
					pos += 1;
				}
				m2[pos] = max(m2[pos], S);
				//cout << "m2 " << pos << " " << S << endl;
			}
			//return 0;
		}
		m = m2;
	}
	int ans = 0;
	for(pair<int, int> p : m){
		ans = max(ans, p.second);
	}
	cout << ans << endl;
	return 0;
}
accuracy: 0.2
time_ms: 220
memory_kb: 3480
final_rank: 18

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

#define fst(t) std::get<0>(t)
#define snd(t) std::get<1>(t)
#define thd(t) std::get<2>(t)
#define unless(p) if(!(p))
#define until(p) while(!(p))

using ll = std::int64_t;
using P = std::tuple<int,int>;

int fact[10];
int N;
int D[120], A[120];
int dp[120][5040];

int f(std::list<int> &perm){
    int s = 0, k = 6, v = 0;

    for(int i : perm){
        v += fact[k] * (i - __builtin_popcount(s & ((1 << i) - 1)) - 1);
        s |= 1 << i;
        k -= 1;
    }

    return v;
}

int rec(int idx, std::list<int> order){
    if(idx == N + 7){
        return 0;
    }

    int fv = f(order);

    if(dp[idx][fv] >= 0){
        return dp[idx][fv];
    }

    int mx = 0;

    for(int i=0;i<=7;++i){
        int v = 0;

        auto it = order.begin();

        for(int j=0;j<7;++j){
            if(j < i){
                if(idx <= idx - *it + D[idx - *it]){
                    v += A[idx - *it];
                }
            }else{
                if(idx - *it >= 7 && idx - D[idx] <= idx - *it){
                    v += A[idx];
                }
            }
            
            std::advance(it, 1);
        }

        std::list<int> newOrder(order);
        std::transform(newOrder.begin(), newOrder.end(), newOrder.begin(), [](int n){return n + 1;});
        newOrder.insert(std::next(newOrder.begin(), i), 1);
        newOrder.remove(8);

        v += rec(idx + 1, newOrder);

        mx = std::max(mx, v);
    }

    return dp[idx][fv] = mx;
}

int main(){
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);

    fact[0] = 1;
    for(int i=1;i<=6;++i){
        fact[i] = i * fact[i - 1];
    }

    std::cin >> N;

    for(int i=0;i<N;++i){
        std::cin >> D[i + 7];
    }

    for(int i=0;i<N;++i){
        std::cin >> A[i + 7];
    }

    std::list<int> order(7);
    std::iota(order.begin(), order.end(), 1);

    memset(dp, -1, sizeof(dp));

    int mx = rec(7, order);
    std::cout << mx << std::endl;
}
accuracy: 1
time_ms: 1720
memory_kb: 5584
final_rank: 13

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
int N;
int D[101];
int A[101];
map<vector<int>, int> perm;

int solve(){
	int dp[101][5040] = {};//今いる所、前７個の順番
	int ans = 0;
	for(int i = 1; i < N; i++){
		vector<int> p = {0, 1, 2, 3, 4, 5, 6, 7};
		do{
			int add = 0;
			bool eaten[8] = {};
			//i番目の小籠包に関する影響のみを考える
			for(int idx = 0; idx < 8; idx++){
				int x = i - p[idx];
				if(x == i){
					eaten[p[idx]] = true;
					for(int d = 1; d <= D[i]; d++){
						if(i - d < 0) continue;
						if(!eaten[d]) add += A[x];
					}
				}
				if(x >= 0){
					eaten[p[idx]] = true;
					if(!eaten[0] && p[idx] <= D[x]){
						add += A[x];
					}
				}
			}
		
			//今の順序の取り出し
			vector<int> tmp1;
			for(int j = 0; j <= 7; j++){
				if(p[j] != 7) tmp1.push_back(p[j]);
			}
			//参照する順序の取り出し
			vector<int> tmp2;
			for(int j = 0; j <= 7; j++){
				if(p[j] != 0) tmp2.push_back(p[j] - 1); 
			}
			dp[i][perm[tmp1]] = max(dp[i][perm[tmp1]], dp[i - 1][perm[tmp2]] + add);
			ans = max(ans, dp[i][perm[tmp1]]);
		}while(next_permutation(p.begin(), p.end()));
	}
	vector<int> p = {0, 1, 2, 3, 4, 5, 6};
	do{
		ans = max(ans, dp[N - 1][perm[p]]);
	}while(next_permutation(p.begin(), p.end()));
	return ans;
}

void init(){
	cin >> N;
	for(int i = 0; i < N; i++){
		cin >> D[i];
	}
	for(int i = 0; i < N; i++){
		cin >> A[i];
	}
	int idx = 0;
	vector<int> p = {0, 1, 2, 3, 4, 5, 6};
	do{	
		for(int i = 0; i < N; i++){
			
		}
		perm[p] = idx++;
	}while(next_permutation(p.begin(), p.end()));
}

int main(){
	init();
	cout << solve() << endl;
	return 0;
}
accuracy: 1
time_ms: 2360
memory_kb: 5776
final_rank: 15

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

//    #include <boost/multiprecision/cpp_int.hpp>
 #define int long long
 #define inf  1000000007
 #define pa pair<int,int>
 #define ll long long
 #define pal pair<double,double>
 #define ppap pair<pa,int>
//  #define PI 3.14159265358979323846
  #define paa pair<int,char>
  #define  mp make_pair
  #define  pb push_back
  #define EPS (1e-10)
                                          
    int dx[8]={0,1,0,-1,1,1,-1,-1};
    int dy[8]={1,0,-1,0,-1,1,1,-1};
                                            using namespace std;
                                   			class pa3{
                                            	public:
                                            	int x,y,z;
                                            	pa3(int x=0,int y=0,int z=0):x(x),y(y),z(z) {}
                                            	bool operator < (const pa3 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		 return z<p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                   				bool operator > (const pa3 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		 return z>p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa3 &p) const{
                                            		return x==p.x && y==p.y && z==p.z;
                                            	}
                                            		bool operator != (const pa3 &p) const{
                                            			return !( x==p.x && y==p.y && z==p.z);
                                            	}
                                            
                                            };
                                            
                                            class pa4{
                                            	public:
                                            	double x;
                                            	int y,z,w;
                                            	pa4(double x=0,int y=0,int z=0,int w=0):x(x),y(y),z(z),w(w) {}
                                            	bool operator < (const pa4 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		if(z!=p.z)return z<p.z;
                                            		return w<p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator > (const pa4 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		if(z!=p.z)return z>p.z;
                                            		return w>p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa4 &p) const{
                                            		return x==p.x && y==p.y && z==p.z &&w==p.w;
                                            	}
                                            		
                                            
                                            };
                                            class pa2{
                                            	public:
                                            	int x,y;
                                            	pa2(int x=0,int y=0):x(x),y(y) {}
                                            	pa2 operator + (pa2 p) {return pa2(x+p.x,y+p.y);}
                                            	pa2 operator - (pa2 p) {return pa2(x-p.x,y-p.y);}
                                            	bool operator < (const pa2 &p) const{
                                            		return y != p.y ? y<p.y: x<p.x;
                                            	}
                                            	bool operator > (const pa2 &p) const{
                                            		return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa2 &p) const{
                                            		return abs(x-p.x)==0 && abs(y-p.y)==0;
                                            	}
                                            	bool operator != (const pa2 &p) const{
                                            		return !(abs(x-p.x)==0 && abs(y-p.y)==0);
                                            	}
                                            		
                                            
                                            };
                                            
/*
                                            class Point{
                                            	public:
                                            	double x,y;
                                            	Point(double x=0,double y=0):x(x),y(y) {}
                                            	Point operator + (Point p) {return Point(x+p.x,y+p.y);}
                                            	Point operator - (Point p) {return Point(x-p.x,y-p.y);}
                                            	Point operator * (double a) {return Point(x*a,y*a);}
                                            	Point operator / (double a) {return Point(x/a,y/a);}
                                            	double absv() {return sqrt(norm());}
                                            	double norm() {return x*x+y*y;}
                                            	bool operator < (const Point &p) const{
                                            		return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const Point &p) const{
                                            		return fabs(x-p.x)<EPS && fabs(y-p.y)<EPS;
                                            	}
                                            };
                                            typedef Point Vector;
                                     #define pl pair<int,pas>
                                            struct Segment{
                                            Point p1,p2;
                                            };
                                             double dot(Vector a,Vector b){
                                            	return a.x*b.x+a.y*b.y;
                                            }
                                            double cross(Vector a,Vector b){
                                            	return a.x*b.y-a.y*b.x;
                                            }
                                        
                bool parareru(Point a,Point b,Point c,Point d){
                //	if(abs(cross(a-b,d-c))<EPS)cout<<"dd "<<cross(a-b,d-c)<<endl;
                	return abs(cross(a-b,d-c))<EPS;
                }
                double distance_ls_p(Point a, Point b, Point c) {
                  if ( dot(b-a, c-a) < EPS ) return (c-a).absv();
                  if ( dot(a-b, c-b) < EPS ) return (c-b).absv();
                  return abs(cross(b-a, c-a)) / (b-a).absv();
                }
                bool is_intersected_ls(Segment a,Segment b) {
                	if(a.p1==b.p1||a.p2==b.p1||a.p1==b.p2||a.p2==b.p2) return false;
                	if(parareru((a.p2),(a.p1),(a.p1),(b.p2))&&parareru((a.p2),(a.p1),(a.p1),(b.p1))){
                //		cout<<"sss"<<endl;
                		if(dot(a.p1-b.p1,a.p1-b.p2)<EPS) return true;
                		if(dot(a.p2-b.p1,a.p2-b.p2)<EPS) return true;
                		if(dot(a.p1-b.p1,a.p2-b.p1)<EPS) return true;
                		if(dot(a.p1-b.p2,a.p2-b.p2)<EPS) return true;
                		return false;
                	}
                  else return ( cross(a.p2-a.p1, b.p1-a.p1) * cross(a.p2-a.p1, b.p2-a.p1) < EPS ) && ( cross(b.p2-b.p1, a.p1-b.p1) * cross(b.p2-b.p1, a.p2-b.p1) < EPS );
                }
                 
                double segment_dis(Segment a,Segment b){
                	if(is_intersected_ls(a,b))return 0;
                	double r=distance_ls_p(a.p1, a.p2, b.p1);
                	r=min(r,distance_ls_p(a.p1, a.p2, b.p2));
                	r=min(r,distance_ls_p(b.p1, b.p2, a.p2));
                	r=min(r,distance_ls_p(b.p1, b.p2, a.p1));
                	return r;
                }
                Point intersection_ls(Segment a, Segment b) {
                  Point ba = b.p2-b.p1;
                  double d1 = abs(cross(ba, a.p1-b.p1));
                  double d2 = abs(cross(ba, a.p2-b.p1));
                  double t = d1 / (d1 + d2);
                 
                  return a.p1 + (a.p2-a.p1) * t;
                }
 */                
                                string itos( int i ) {
                                ostringstream s ;
                                s << i ;
                                return s.str() ;
                                }
                                 
                                int gcd(int v,int b){
                                	if(v>b) return gcd(b,v);
                                	if(v==b) return b;
                                	if(b%v==0) return v;
                                	return gcd(v,b%v);
                                }
                 
                                double distans(double x1,double y1,double x2,double y2){
                                	double rr=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
                                	return sqrt(rr);
                                	
                                }
                                int mod;
                                
                int pr[500010];
                int inv[500010];
                
                int beki(int wa,int rr,int warukazu){
                	if(rr==0) return 1%warukazu;
                	if(rr==1) return wa%warukazu;
                	if(rr%2==1) return ((ll)beki(wa,rr-1,warukazu)*(ll)wa)%warukazu;
                	ll zx=beki(wa,rr/2,warukazu);
                	return (zx*zx)%warukazu;
                }
    double bekid(double w,int r){
    	if(r==0) return 1.0;
    	if(r==1) return w;
    	if(r%2) return bekid(w,r-1)*w;
    	double f=bekid(w,r/2);
    	return f*f;
    }
                
    			int comb(int nn,int rr){
    				int r=pr[nn]*inv[rr];
    				r%=mod;
    				r*=inv[nn-rr];
    				r%=mod;
    				return r;
    			}
                
                void gya(int ert){
                	pr[0]=1;
                	for(int i=1;i<ert;i++){
                		pr[i]=(pr[i-1]*i)%mod;
                	}
                	for(int i=0;i<ert;i++) inv[i]=beki(pr[i],mod-2,mod);
                	
                }
                
              //   cin.tie(0);
    		//	ios::sync_with_stdio(false);
    			//priority_queue<pa3,vector<pa3>,greater<pa3>> pq;            
                 //sort(ve.begin(),ve.end(),greater<int>());
                                         //----------------kokomade tenpure------------
                //vector<double> ans(100000000),ans2(100000000)
      

vector<int> ve[5040];
map<vector<int>,int> ma;

int x[1010],y[1010];

int dp[102][5040];
int a[110],d[110];
  signed main(){
    	       cin.tie(0);
    			ios::sync_with_stdio(false);
int n;
vector<int> f;
  	for(int i=0;i<7;i++)f.pb(i);
  	int cnt=0;
  	do{
  		ma[f]=cnt;
  		ve[cnt]=f;
  		cnt++;
  	}while(next_permutation(f.begin(),f.end()));
  	//cout<<cnt<<endl;
  	cin>>n;
  	
  	for(int i=0;i<n;i++)cin>>d[i];
  	for(int i=0;i<n;i++)cin>>a[i];
  	
  	for(int i=0;i<=n;i++)for(int j=0;j<5040;j++)dp[i][j]=-inf;
  	dp[0][0]=0;
  	
  	for(int i=0;i<n-1;i++)for(int j=0;j<5040;j++)if(dp[i][j]>=0){
  		for(int b=0;b<=7;b++){
  			vector<int> v=ve[j];
  		
  			for(int k=0;k<7;k++)if(v[k]>=b)v[k]++;
  			
  		
  			int ans=dp[i][j];
  			for(int k=0;k<7;k++)if(i-k>=0)if(d[i-k]>=1+k)if(v[k]<b)ans+=a[i-k];
  			for(int k=0;k<7;k++)if(i-k>=0)if(d[i+1]>=k+1)if(v[k]>b)ans+=a[i+1];
  			v.insert(v.begin(),b);
  			for(int k=0;k<7;k++)if(v[k]>v[7])v[k]--;
  			v.pop_back();
  			if(ma.find(v)==ma.end()){
  				for(auto vv:v)cout<<vv<<" ";
  				cout<<endl;
  				cout<<"dame"<<endl;
  				exit(1);
  			}
  			int num=ma[v];
  			//for(auto vv:v)cout<<vv<<" ";
  			//	cout<<"   "<<ans<<endl;
  			dp[i+1][num]=max(dp[i+1][num],ans);
  		
  		}
  		
  	}
  	int e=0;
  	for(int i=0;i<5040;i++)e=max(e,dp[n-1][i]);
  	cout<<e<<endl;
  	
  	
  	return 0;
    }
accuracy: 1
time_ms: 950
memory_kb: 8252
final_rank: 11

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

map<vector<int>, int>init(vector<int>ds, vector<int>as) {
	vector<int>perms(ds.size());
	iota(perms.begin(),perms.end(),0);

	map<vector<int>,int>mp;
	do {
		int nans=0;
		vector<int>dels(ds.size());
		for (auto eat : perms) {
			nans+=dels[eat];
			for (int x = eat - ds[eat]; x <= eat + ds[eat];++x) {
				if (x >= 0 && x < ds.size()) {
					dels[x]+=as[eat];
				}
			}
			
		}
		mp[perms]=nans;
	}while(next_permutation(perms.begin(),perms.end()));
	return mp;
}

map<vector<int>, int>comp_memo(map<vector<int>, int>pr_memo) {
	map<vector<int>,int>ne_memo;
	for (auto pm : pr_memo) {
		auto v(pm.first);
		int f_num = v[0];
		v.erase(find(v.begin(),v.end(),0));
		for (auto&c : v) {
			c--;
		}
		ne_memo[v]=max(ne_memo[v],pm.second);
	}
	return ne_memo;
}

map<vector<int>, int>update(vector<int>ds, vector<int>as,map<vector<int>,int>pr_memo) {
	pr_memo=comp_memo(pr_memo);
	vector<int>perms(ds.size());
	iota(perms.begin(), perms.end(), 0);

	map<vector<int>, int>mp;
	do {
		int nans = 0;
		vector<int>dels(ds.size());
		for (auto eat : perms) {
			nans += dels[eat];

			for (int x = eat - ds[eat]; x <= eat + ds[eat];++x) {
				if (x >= 0 && x < ds.size()) {
					if (eat == ds.size() - 1 || x == ds.size() - 1) {
						dels[x] += as[eat];
					}
				}
			}
		}
		vector<int>v(perms.begin(),perms.end());
		v.erase(find(v.begin(),v.end(),ds.size()-1));
		assert(pr_memo.find(v)!=pr_memo.end());
		nans+=pr_memo[v];
		mp[perms] = max(nans,mp[perms]);
	} while (next_permutation(perms.begin(), perms.end()));
	return mp;
}

int main() {
	int N;cin>>N;
	vector<int>ds(N),as(N);
	for (int i = 0; i < N; ++i) {
		cin>>ds[i];
	}
	for (int i = 0; i < N; ++i) {
		cin>>as[i];
	}

	if (N <= 8) {
		auto ans_mp(init(ds,as));

		int ans=0;
		for (auto am : ans_mp) {
			ans=max(am.second,ans);
		}
		cout<<ans<<endl;
	}
	else {
		auto memo(init(vector<int>(ds.begin(),ds.begin()+8),vector<int>(as.begin(),as.begin()+8)));
		for (int i = 8; i < N; ++i) {
			memo=update(vector<int>(ds.begin()+i-7,ds.begin()+i+1)
				,vector<int>(as.begin()+i-7,as.begin()+i+1),memo);
		}
		int ans=0;
		for (auto am : memo) {
			ans=max(am.second,ans);
			//cout<<ans<<endl;
		}
		cout<<ans<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 3990
memory_kb: 18892
final_rank: 16

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

map<vector<int>, int>init(vector<int>ds, vector<int>as) {
	vector<int>perms(ds.size());
	iota(perms.begin(),perms.end(),0);

	map<vector<int>,int>mp;
	do {
		int nans=0;
		vector<int>dels(ds.size());
		for (auto eat : perms) {
			nans+=dels[eat];
			for (int x = eat - ds[eat]; x <= eat + ds[eat];++x) {
				if (x >= 0 && x < ds.size()) {
					dels[x]+=as[eat];
				}
			}
			
		}
		mp[perms]=nans;
	}while(next_permutation(perms.begin(),perms.end()));
	return mp;
}

map<vector<int>, int>comp_memo(map<vector<int>, int>pr_memo) {
	map<vector<int>,int>ne_memo;
	for (auto pm : pr_memo) {
		auto v(pm.first);
		int f_num = v[0];
		v.erase(v.begin());
		for (auto&x : v) {
			if (x > f_num) {
				x--;
			}
		}
		ne_memo[v]=max(ne_memo[v],pm.second);
	}
	return ne_memo;
}

map<vector<int>, int>update(vector<int>ds, vector<int>as,map<vector<int>,int>pr_memo) {
	pr_memo=comp_memo(pr_memo);
	vector<int>perms(8);
	iota(perms.begin(), perms.end(), 0);

	map<vector<int>, int>mp;
	do {
		int nans = 0;
		vector<int>dels(ds.size());
		for (auto eat : perms) {
			nans += dels[eat];

			for (int x = eat - ds[eat]; x <= eat + ds[eat];++x) {
				if (x >= 0 && x < ds.size()) {
					if (eat == ds.size() - 1 || x == ds.size() - 1) {
						dels[x] += as[eat];
					}
				}
			}
			
		}
		vector<int>v(perms.begin(),perms.end()-1);
		int last_eat=perms.back();
		for (auto &a : v) {
			if(a>last_eat)a--;
		}
		assert(pr_memo.find(v)!=pr_memo.end());
		nans+=pr_memo[v];
		mp[perms] = max(nans,mp[perms]);
	} while (next_permutation(perms.begin(), perms.end()));
	return mp;
}

int main() {
	int N;cin>>N;
	vector<int>ds(N),as(N);
	for (int i = 0; i < N; ++i) {
		cin>>ds[i];
	}
	for (int i = 0; i < N; ++i) {
		cin>>as[i];
	}

	if (N <= 8) {
		auto ans_mp(init(ds,as));

		int ans=0;
		for (auto am : ans_mp) {
			ans=max(am.second,ans);
		}
		cout<<ans<<endl;
	}
	else {
		auto memo(init(vector<int>(ds.begin(),ds.begin()+8),vector<int>(as.begin(),as.begin()+8)));
		for (int i = 8; i < N; ++i) {
			memo=update(vector<int>(ds.begin()+i-7,ds.begin()+i+1)
				,vector<int>(as.begin()+i-7,as.begin()+i+1),memo);
		}
		int ans=0;
		for (auto am : memo) {
			ans=max(am.second,ans);
		}
		cout<<ans<<endl;
	}
	return 0;
}
accuracy: 0.2
time_ms: 4020
memory_kb: 18844
final_rank: 19

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

typedef vector<int> V;

int N;
int M;
int ans;
int fact;
int D[114];
int A[114];
int dp[114][114514];
int nxt[114514][10];
V perm;
vector<V> perms;
map<V, int> rev;

int main() {
  scanf("%d", &N);
  for (int i=0; i<N; i++) {
    scanf("%d", &D[i]);
    M = max(M, D[i]+1);
  }
  M = min(M, N);

  for (int i=0; i<N; i++) {
    scanf("%d", &A[i]);
  }
  //reverse(A, A+N);
  //reverse(D, D+N);

  fact = 1;
  for (int i=0; i<M; i++) {
    perm.emplace_back(i);
    fact *= i+1;
  }

  for (int i=0; i<fact; i++) {
    rev[perm] = i;
    perms.emplace_back(perm);
    next_permutation(perm.begin(), perm.end());
  }

  for (int idx=0; idx<fact; idx++) {
    auto &perm = perms[idx];
    for (int k=0; k<=M; k++) {
      V nperm;
      for (int l=0; l<k; l++) {
        int p = perm[l];
        if (p > 0) nperm.emplace_back(p-1);
      }
      nperm.emplace_back(M-1);
      for (int l=k; l<M; l++) {
        int p = perm[l];
        if (p > 0) nperm.emplace_back(p-1);
      }
      assert(rev.count(nperm));
      nxt[idx][k] = rev[nperm];
    }
  }

  for (int idx=0; idx<fact; idx++) {
    int initial = 0;
    int conv[10] = {};
    
    for (int p : perms[idx]) {
      initial += conv[p];
      for (int k=0; k<M; k++) {
        if (p-D[p] <= k && k <= p+D[p]) conv[k] += A[p];
      }
    }

    dp[M-1][idx] = initial;
    ans = max(ans, initial);
  }

  for (int i=M; i<N; i++) {
    for (int j=0; j<fact; j++) {
      auto &perm = perms[j];
      for (int k=0; k<=M; k++) {
        int conv = 0;
        for (int l=0; l<k; l++) {
          int p = perm[l];
          if (M <= p+D[i-M+p]) conv += A[i-M+p];
        }

        int lack = 0;
        for (int l=k; l<M; l++) {
          int p = perm[l];
          if (M-D[i] <= p) lack += A[i];
        }

        int nj = nxt[j][k];
        dp[i][nj] = max(dp[i][nj], dp[i-1][j]+conv+lack);
        ans = max(ans, dp[i][nj]);
      }
    }
  }

  printf("%d\n", ans);
}
accuracy: 1
time_ms: 470
memory_kb: 27400
final_rank: 14