Problem:
C - Iyasugigappa
Problem Statement
Three animals Frog, Kappa (Water Imp) and Weasel are playing a card game.
In this game, players make use of three kinds of items: a guillotine, twelve noble cards and six action cards. Some integer value is written on the face of each noble card and each action card. Before stating the game, players put twelve noble cards in a line on the table and put the guillotine on the
right
of the noble cards. And then each player are dealt two action cards. Here, all the noble cards and action cards are opened, so the players share all the information in this game.
Next, the game begins. Each player takes turns in turn. Frog takes the first turn, Kappa takes the second turn, Weasel takes the third turn, and Frog takes the fourth turn, etc. Each turn consists of two phases: action phase and execution phase in this order.
In action phase, if a player has action cards, he may use one of them. When he uses an action card with value on the face
y
,
y
-th (1-based) noble card from the front of the guillotine on the table is moved to in front of the guillotine, if there are at least
y
noble cards on the table. If there are less than
y
cards, nothing happens. After the player uses the action card, he must discard it from his hand.
In execution phase, a player just remove a noble card in front of the guillotine. And then the player scores
x
points, where
x
is the value of the removed noble card.
The game ends when all the noble cards are removed.
Each player follows the following strategy:
Each player assume that other players would follow a strategy such that their final score is maximized.
Actually, Frog and Weasel follows such strategy.
However, Kappa does not. Kappa plays so that Frog's final score is minimized.
Kappa knows that Frog and Weasel would play under ``wrong'' assumption: They think that Kappa would maximize his score.
As a tie-breaker of multiple optimum choises for each strategy, assume that players prefer to keep as many action cards as possible at the end of the turn.
If there are still multiple optimum choises, players prefer to maximuze the total value of remaining action cards.
Your task in this problem is to calculate the final score of each player.
Input
The input is formatted as follows.
x_{12}
x_{11}
x_{10}
x_9
x_8
x_7
x_6
x_5
x_4
x_3
x_2
x_1
y_1
y_2
y_3
y_4
y_5
y_6
The first line of the input contains twelve integers
x_{12}
,
x_{11}
, …,
x_{1}
(
-2 \leq x_i \leq 5
).
x_i
is integer written on
i
-th noble card from the guillotine.
Following three lines contains six integers
y_1
, …,
y_6
(
1 \leq y_j \leq 4
).
y_1
,
y_2
are values on Frog's action cards,
y_3
,
y_4
are those on Kappa's action cards, and
y_5
,
y_6
are those on Weasel's action cards.
Output
Print three space-separated integers: the final scores of Frog, Kappa and Weasel.
Sample Input 1
3 2 1 3 2 1 3 2 1 3 2 1
1 1
1 1
1 1
Output for the Sample Input 1
4 8 12
Sample Input 2
4 4 4 3 3 3 2 2 2 1 1 1
1 2
2 3
3 4
Output for the Sample Input 2
8 10 
...(truncated)

Submitted solutions:

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 = 998244353;
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 << 2;
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 nexid(int id) {
	if (id == 2)return 0;
	return id + 1;
}
bool isfin(int x) {
	return x % (1 << 12) == 0;
}
int nex[1 << 18][2];
int ad[1 << 18][2];
void solve() {
	vector<int> x(18); rep(i, 18)cin >> x[i];
	rep(i, 1 << 18)rep(j, 2) {
		if (i % (1 << 12) == 0)continue;
		vector<int> v;
		rep(j, 12)if (i & (1 << j)) {
			v.push_back(j);
		}
		int id = 0;
		if (v.size() % 3 == 2)id = 1;
		else if (v.size() % 3 == 1)id = 2;
		
		int ori = mod;
		int oriactnum = mod;
		int oriact = mod;
		int chk = -1;
		auto upd = [&](int val, int actnum, int act) {
			if (ori == mod)return true;
			if (ori != val) {
				if (id == 1 && j == 1) {
					return ori > val;
				}
				else return ori < val;
			}
			if (oriactnum != actnum)return oriactnum > actnum;
			return oriact > act;
		};
		vector<int> ni(3);

		vector<int> adi(3);
		vector<int> actnum(3);
		vector<int> act(3);

		vector<bool> can(3);
		ni[0] = i ^ (1 << v.back());
		adi[0] = x[v.back()];
		can[0] = true;
		actnum[0] = 0;
		act[0] = 0;
		if (i & (1 << (12 + 2 * id))) {
			if (x[12 + 2 * id] <= v.size()) {
				int loc = v.size() - x[12 + 2 * id];
				loc = v[loc];
				ni[1] = i ^ (1 << loc)^(1<<(12+2*id));
				adi[1] = x[loc];
				can[1] = true;
				actnum[1] = 1;
				act[1] = x[12 + 2 * id];
			}
		}
		if (i & (1 << (12 + 2 * id+1))) {
			if (x[12 + 2 * id+1] <= v.size()) {
				int loc = v.size() - x[12 + 2 * id+1];
				loc = v[loc];
				ni[2] = i ^ (1 << loc) ^ (1 << (12 + 2 * id+1));
				adi[2] = x[loc];
				can[2] = true;
				actnum[2] = 1;
				act[2] = x[12 + 2 * id+1];
			}
		}
		rep(t, 3)if(can[t]) {
			int sum[3] = {};
			int z = j;
			if (id != 1)z = 0;
			int cur = ni[t];
			int curid = id;
			curid = nexid(curid);
			sum[id] += adi[t];
			while (!isfin(cur)) {
				sum[curid] += ad[cur][z];
				cur = nex[cur][z];
				curid = nexid(curid);
			}
			int val;
			if (id == 1 && j == 1) {
				val = sum[0];
			}
			else {
				val = sum[id];
			}
			if (upd(val, actnum[t], act[t])) {
				ori = val;
				oriactnum = actnum[t];
				oriact = act[t];
				chk = t;
			}
		}
		nex[i][j] = ni[chk];
		ad[i][j] = adi[chk];
	}
	int cur = (1 << 18) - 1;
	int sum[3] = {};
	int curid = 0;
	while (!isfin(cur)) {
		sum[curid] += ad[cur][1];
		cur = nex[cur][1];
		curid = nexid(curid);
		/*cout << curid << " ";
		rep(i, 12) {
			if (cur & (1 << i))cout << 1;
			else cout << 0;
		}cout << "\n";*/
	}
	cout << sum[0] << " " << sum[1] << " " << sum[2] << "\n";
}



signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(8);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 7552
final_rank: 4

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

#define BIG_NUM 1000
#define NUM 531441

enum Type{
	FROG,
	Kappa,
	Weasel,
};

enum ACT{
	USE_1,
	USE_2,
	NONE,
};

struct Info{

	short result[3];
};

int POW[12];
int noble[12],action[3][2];
int work[12],value[3];
Type type_array[3] = {FROG,Kappa,Weasel};
ACT act_array[3] = {USE_1,USE_2,NONE},history[12];
Info dp[2][12][NUM];

Info recursive(int turn,int state,bool kappa_mind){

	if(turn == 12){

		Info ret;

		for(int i = 0; i < 3; i++){

			ret.result[i] = value[i];
		}

		return ret;
	}

	if(dp[kappa_mind][turn][state].result[0] != -(BIG_NUM+1)){

		return dp[kappa_mind][turn][state];
	}

	bool did_use[2] = {false,false};
	Type type = type_array[(turn)%3];

	int pre_work[12];

	for(int k = 0; k < 12; k++){

		pre_work[k] = work[k];
	}

	for(int i = (turn%3); i < turn; i += 3){

		if(history[i] == USE_1){

			did_use[USE_1] = true;

		}else if(history[i] == USE_2){

			did_use[USE_2] = true;
		}
	}

	Info tmp[3];

	if(kappa_mind == false || type == Kappa){

		if(kappa_mind == false){

			tmp[USE_1].result[type] = -BIG_NUM;
			tmp[USE_2].result[type] = -BIG_NUM;

		}else{

			tmp[USE_1].result[FROG] = BIG_NUM;
			tmp[USE_2].result[FROG] = BIG_NUM;
		}

		int rest_num = 12-turn;

		if(!did_use[USE_1]){

			int pre_value = value[type];

			if(rest_num >= action[type][USE_1]){

				value[type] += work[action[type][USE_1]-1];

				for(int k = action[type][USE_1]; k < 12; k++){

					work[k-1] = work[k];
				}
			}else{

				value[type] += work[0];

				for(int k = 1; k < 12; k++){

					work[k-1] = work[k];
				}
			}

			history[turn] = USE_1;
			tmp[USE_1] = recursive(turn+1,state,kappa_mind);

			for(int i = 0; i < 12; i++){

				work[i] = pre_work[i];
			}

			value[type] = pre_value;
		}

		if(!did_use[USE_2]){

			int pre_value = value[type];

			if(rest_num >= action[type][USE_2]){

				value[type] += work[action[type][USE_2]-1];

				for(int k = action[type][USE_2]; k < 12; k++){

					work[k-1] = work[k];
				}
			}else{

				value[type] += work[0];

				for(int k = 1; k < 12; k++){

					work[k-1] = work[k];
				}
			}

			history[turn] = USE_2;
			tmp[USE_2] = recursive(turn+1,state+POW[turn],kappa_mind);

			for(int i = 0; i < 12; i++){

				work[i] = pre_work[i];
			}

			value[type] = pre_value;
		}

		int pre_value = value[type];

		value[type] += work[0];

		for(int k = 1; k < 12; k++){

			work[k-1] = work[k];
		}

		history[turn] = NONE;

		tmp[NONE] = recursive(turn+1,state+2*POW[turn],kappa_mind);

		for(int i = 0; i < 12; i++){

			work[i] = pre_work[i];
		}

		value[type] = pre_value;

		if(kappa_mind == false){

			int max_value = -BIG_NUM,num_max = 0;
			ACT max_act;

			for(int i = 0; i < 3; i++){

				if(max_value < tmp[act_array[i]].result[type]){

					max_value = tmp[act_array[i]].result[type];
					max_act = act_array[i];
					num_max = 1;
				}else if(max_value == tmp[act_array[i]].result[type]){

					num_max++;
				}
			}

			if(num_max == 1){

				return dp[kappa_mind][turn][state] = tmp[max_act];

			}else if(num_max == 3){

				return dp[kappa_mind][turn][state] = tmp[NONE];

			}else{ //num_max == 2

				if(tmp[USE_1].result[type] < max_value){

					return dp[kappa_mind][turn][state] = tmp[NONE];

				}else if(tmp[USE_2].result[type] < max_value){

					return dp[kappa_mind][turn][state] = tmp[NONE];

				}else{ //tmp[NONE].result[type] < max_value

					if(action[type][USE_1] < action[type][USE_2]){

						return dp[kappa_mind][turn][state] = tmp[USE_1];

					}else{

						return dp[kappa_mind][turn][state] = tmp[USE_2];
					}
				}
			}

		}else{

			int min_value = BIG_NUM,num_min = 0;
			ACT min_act;

			for(int i = 0; i < 3; i++){

				if(min_value > tmp[act_array[i]].result[FROG]){

					min_value = tmp[act_array[i]].result[FROG];
					min_act = act_array[i];
					num_min = 1;
				}else if(min_value == tmp[act_array[i]].result[FROG]){

					num_min++;
				}
			}

			if(num_min == 1){

				return dp[kappa_mind][turn][state] = tmp[min_act];

			}else if(num_min == 3){

				return dp[kappa_mind][turn][state] = tmp[NONE];

			}else{ //num_min == 2

				if(tmp[USE_1].result[FROG] > min_value){

					return dp[kappa_mind][turn][state] = tmp[NONE];

				}else if(tmp[USE_2].result[FROG] > min_value){

					return dp[kappa_mind][turn][state] = tmp[NONE];

				}else{ //tmp[NONE].result[FROG] > min_value

					if(action[type][USE_1] < action[type][USE_2]){

						return dp[kappa_mind][turn][state] = tmp[USE_1];

					}else{

						return dp[kappa_mind][turn][state] = tmp[USE_2];
					}
				}
			}
		}

	}else{

		tmp[USE_1].result[type] = -BIG_NUM;
		tmp[USE_2].result[type] = -BIG_NUM;

		int rest_num = 12-turn;

		if(!did_use[USE_1]){

			int pre_value = value[type];

			if(rest_num >= action[type][USE_1]){

				value[type] += work[action[type][USE_1]-1];

				for(int k = action[type][USE_1]; k < 12; k++){

					work[k-1] = work[k];
				}
			}else{

				value[type] += work[0];

				for(int k = 1; k < 12; k++){

					work[k-1] = work[k];
				}
			}

			history[turn] = USE_1;
			tmp[USE_1] = recursive(turn+1,state,false);

			for(int i = 0; i < 12; i++){

				work[i] = pre_work[i];
			}

			value[type] = pre_value;
		}

		if(!did_use[USE_2]){

			int pre_value = value[type];

			if(rest_num >= action[type][USE_2]){

				value[type] += work[action[type][USE_2]-1];

				for(int k = action[type][USE_2]; k < 12; k++){

					work[k-1] = work[k];
				}
			}else{

				value[type] += work[0];

				for(int k = 1; k < 12; k++){

					work[k-1] = work[k];
				}
			}

			history[turn] = USE_2;
			tmp[USE_2] = recursive(turn+1,state+POW[turn],false);

			for(int i = 0; i < 12; i++){

				work[i] = pre_work[i];
			}

			value[type] = pre_value;
		}

		int pre_value = value[type];

		value[type] += work[0];

		for(int k = 1; k < 12; k++){

			work[k-1] = work[k];
		}

		history[turn] = NONE;

		tmp[NONE] = recursive(turn+1,state+2*POW[turn],false);

		for(int i = 0; i < 12; i++){

			work[i] = pre_work[i];
		}

		value[type] = pre_value;

		int max_value = -BIG_NUM,num_max = 0;
		ACT max_act;

		for(int i = 0; i < 3; i++){

			if(max_value < tmp[act_array[i]].result[type]){

				max_value = tmp[act_array[i]].result[type];
				max_act = act_array[i];
				num_max = 1;
			}else if(max_value == tmp[act_array[i]].result[type]){

				num_max++;
			}
		}

		Info ret2;

		if((num_max == 1 && max_act == NONE) || (num_max == 3) || (num_max == 2 && tmp[USE_1].result[type] < max_value) ||
				(num_max == 2 && tmp[USE_2].result[type] < max_value)){ //NONE

			pre_value = value[type];

			value[type] += work[0];

			for(int k = 1; k < 12; k++){

				work[k-1] = work[k];
			}

			history[turn] = NONE;

			ret2 = recursive(turn+1,state+2*POW[turn],true);

			for(int i = 0; i < 12; i++){

				work[i] = pre_work[i];
			}

			value[type] = pre_value;

		}else if((num_max == 1 && max_act == USE_1) ||
				(tmp[NONE].result[type] < max_value && num_max == 2 && action[type][USE_1] < action[type][USE_2])){ //USE_1

			int pre_value = value[type];

			if(rest_num >= action[type][USE_1]){

				value[type] += work[action[type][USE_1]-1];

				for(int k = action[type][USE_1]; k < 12; k++){

					work[k-1] = work[k];
				}
			}else{

				value[type] += work[0];

				for(int k = 1; k < 12; k++){

					work[k-1] = work[k];
				}
			}

			history[turn] = USE_1;
			ret2 = recursive(turn+1,state,true);

			for(int i = 0; i < 12; i++){

				work[i] = pre_work[i];
			}

			value[type] = pre_value;

		}else{ //USE_2

			int pre_value = value[type];

			if(rest_num >= action[type][USE_2]){

				value[type] += work[action[type][USE_2]-1];

				for(int k = action[type][USE_2]; k < 12; k++){

					work[k-1] = work[k];
				}
			}else{

				value[type] += work[0];

				for(int k = 1; k < 12; k++){

					work[k-1] = work[k];
				}
			}

			history[turn] = USE_2;
			ret2 = recursive(turn+1,state+POW[turn],true);

			for(int i = 0; i < 12; i++){

				work[i] = pre_work[i];
			}

			value[type] = pre_value;
		}

		return dp[kappa_mind][turn][state] = ret2;
	}
}

int main(){

	POW[0] = 1;

	for(int i = 1; i < 12; i++){

		POW[i] = POW[i-1]*3;
	}

	for(int i = 0; i < 12; i++){

		scanf("%d",&noble[i]);
	}

	for(int i = 0; i < 3; i++){

		scanf("%d %d",&action[type_array[i]][0],&action[type_array[i]][1]);
	}

	for(int i = 0; i < 12; i++){

		work[i] = noble[11-i];
	}

	for(int i = 0; i < 3; i++){

		value[i] = 0;
	}

	for(int i = 0; i < 2; i++){
		for(int k = 0; k < 12; k++){
			for(int state = 0; state < NUM; state++){
				for(int a = 0; a < 3; a++){
					dp[i][k][state].result[a] = -(BIG_NUM+1);
				}
			}
		}
	}

	recursive(0,0,false);
	Info ret = recursive(0,0,true);

	printf("%d %d %d\n",ret.result[FROG],ret.result[Kappa],ret.result[Weasel]);

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 77948
final_rank: 3

code_snippet: #include <vector>
#include <iostream>
#include <utility>
#include <algorithm>
#include <string>
#include <deque>
#include <tuple>
#include <queue>
#include <stack>
#include <functional>
#include <cmath>
#include <iomanip>
#include <map>
#include <set>
#include <numeric>
#include <unordered_map>
#include <unordered_set>
#include <complex>
#include <iterator>
#include <array>
#include <memory>
#include <random>
#include <valarray>
//cin.sync_with_stdio(false);
//streambuf
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
using vi = vector<int>;
using vll = vector<ll>;
using vpii = vector<pii>;
using vpll = vector<pll>;
using ti3 = tuple<int, int, int>;
using vti3 = vector<ti3>;
template<class T, int s>using va = vector<array<T, s>>;
template<class T, class T2> using umap = unordered_map<T, T2>;
template<class T> using uset = unordered_set<T>;
template<class T, class S> void cmin(T &a, const S &b) { if (a > b)a = b; }
template<class T, class S> void cmax(T &a, const S &b) { if (a < b)a = b; }
#define ALL(a) a.begin(),a.end()
#define rep(i,a) for(int i=0;i<a;i++)
#define rep1(i,a) for(int i=1;i<=a;i++)
#define rrep(i,a) for(int i=(a)-1;i>=0;i--)
#define rrep1(i,a) for(int i=a;i;i--)
#define repi(i,a,b) for(int i=a;i<b;i++)
const ll mod = 1000000007;
template<class T>using heap = priority_queue<T, vector<T>, greater<T>>;
template<class T>using pque = priority_queue<T, vector<T>, function<T(T, T)>>;
template <class T>
inline void hash_combine(size_t & seed, const T & v) {
	hash<T> hasher;
	seed ^= hasher(v) + 0x9e3779b97f4a7c15 + (seed << 6) + (seed >> 2);
}
namespace std {
	template<typename S, typename T> struct hash<pair<S, T>> {
		inline size_t operator()(const pair<S, T> & v) const {
			size_t seed = 0;
			hash_combine(seed, v.first);
			hash_combine(seed, v.second);
			return seed;
		}
	};
	// Recursive template code derived from Matthieu M.
	template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
	struct HashValueImpl {
		static void apply(size_t& seed, Tuple const& tuple) {
			HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
			hash_combine(seed, std::get<Index>(tuple));
		}
	};
	template <class Tuple>
	struct HashValueImpl<Tuple, 0> {
		static void apply(size_t& seed, Tuple const& tuple) {
			hash_combine(seed, std::get<0>(tuple));
		}
	};
	template <typename ... TT>
	struct hash<std::tuple<TT...>> {
		size_t operator()(std::tuple<TT...> const& tt) const {
			size_t seed = 0;
			HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
			return seed;
		}
	};
}
template<class T>int id(vector<T> &a, T b) {
	return lower_bound(ALL(a), b) - a.begin();
}
ll pow(ll base, ll i, ll mod) {
	ll a = 1;
	while (i) {
		if (i & 1) {
			a *= base;
			a %= mod;
		}
		base *= base;
		base %= mod;
		i /= 2;
	}
	return a;
}
ll gcd(ll a, ll b) {
	while (b) {
		ll c = a%b;
		a = b;
		b = c;
	}
	return a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b)*b;
}
#ifdef _MSC_VER
#include <intrin.h>
#endif
int popcnt(unsigned long long a) {
#ifndef _MSC_VER
	return __builtin_popcountll(a);
#else
	return _mm_popcnt_u32(a >> 32) + _mm_popcnt_u32(a);
	a = (a & 0x5555555555555555) + (a >> 1 & 0x5555555555555555);
	a = (a & 0x3333333333333333) + (a >> 2 & 0x3333333333333333);
	a = (a & 0x0f0f0f0f0f0f0f0f) + (a >> 4 & 0x0f0f0f0f0f0f0f0f);
	a = (a & 0x00ff00ff00ff00ff) + (a >> 8 & 0x00ff00ff00ff00ff);
	a = (a & 0x0000ffff0000ffff) + (a >> 16 & 0x0000ffff0000ffff);
	return (a & 0xffffffff) + (a >> 32);
#endif
}
int BitScanF(unsigned long a) {
#ifndef _MSC_VER
	return __builtin_ctz(a);
#else
	_BitScanForward(&a, a);
	return a;
#endif
}
int BitScanR(unsigned long a) {
#ifndef _MSC_VER
	return 63 - __builtin_clz(a);
#else
	_BitScanReverse(&a, a);
	return a;
#endif
}
template<class T>
class matrix {
public:
	vector<valarray<T>> obj;
	pair<int, int> s;
public:
	matrix(pair<int, int> size, T e = 0) :matrix(size.first, size.second, e) {}
	matrix(int n, int m = -1, T e = 0) :obj(n, valarray<T>(e, m == -1 ? n : m)), s(n, m == -1 ? n : m) {}
	static matrix e(int n) {
		matrix a = (n);
		for (int i = 0; i < n; i++)a[i][i] = 1;
		return a;
	}
	matrix& operator+=(const matrix &p) {
		if (s != p.s)throw runtime_error("matrix error");
		for (int i = 0; i < s.first; i++)
			for (int j = 0; j < s.second; j++)obj[i][j] += p.obj[i][j];
		return *this;
	}
	matrix operator+(const matrix &p) {
		matrix res(*this);
		return res += p;
	}
	matrix& operator-=(const matrix &p) {
		if (s != p.s)throw runtime_error("matrix error");
		for (int i = 0; i < s.first; i++)
			for (int j = 0; j < s.second; j++)obj[i][j] -= p.obj[i][j];
		return *this;
	}
	matrix operator-(const matrix &p) {
		matrix res(*this);
		return res -= p;
	}
	matrix& operator*=(T p) {
		for (auto &a : obj)
			for (auto &b : a)b *= p;
		return *this;
	}
	matrix operator*(T p) {
		matrix res(*this);
		return res *= p;
	}
	matrix operator*(const matrix &p) {
		if (s.second != p.s.first)throw runtime_error("matrix error");
		matrix ret(s.first, p.s.second);
		for (int i = 0; i < s.first; i++)
			for (int j = 0; j < s.second; j++)ret[i] += obj[i][j] * p.obj[j];
		return ret;
	}
	matrix &operator*=(const matrix &p) {
		return *this = *this*p;
	}
	bool operator==(const matrix&p) {
		if (s != p.s)return 0;
		rep(i, s.first)rep(j, s.second)if (obj[i][j] != p.obj[i][j])return 0;
		return 1;
	}
	pair<int, int> size() const {
		return s;
	}
	matrix &mod(T m) {
		for (auto &a : obj)
			for (auto &b : a)b %= m;
		return *this;
	}
	valarray<T>& operator[](int t) {
		return obj[t];
	}
	void gauss() {
		if (size().first + 1 != size().second)return;
		rep(i, size().first) {
			int p = i;
			repi(j, i, size().first)if (abs(obj[j][i]) > abs(obj[p][i]))p = j;
			swap(obj[i], obj[p]);
			if (abs(obj[i][i]) < 1e-8)return;//contniue;
			repi(j, i + 1, size().second)obj[i][j] /= obj[i][i];
			rep(j, size().first) {
				if (i != j) {
					repi(k, i + 1, size().second)obj[j][k] -= obj[j][i] * obj[i][k];
				}
			}
		}
	}
};
template<class T> inline
matrix<T> pow(matrix<T> &base, unsigned long long exp) {
	auto base_(base);
	if (base_.size().first != base_.size().second)throw runtime_error("matrix error");
	matrix<T> res = matrix<T>::e(base_.size().first);
	for (;;) {
		if (exp & 1)res *= base_;
		if (res.obj[0].size() > 100) {
			int a=0;
		}
		if (!(exp /= 2))break;
		base_ *= base_;
	}
	return res;
}
template<class T> inline
matrix<T> modpow(matrix<T> &base, unsigned long long exp, ll m) {
	auto base_(base);
	if (base.size().first != base_.size().second)throw runtime_error("matrix error");
	matrix<T> res = matrix<T>::e(base_.size().first);
	for (;;) {
		if (exp & 1)(res *= base_).mod(m);
		if (res.obj[0].size() > 100) {
			int a = 0;
		}
		if (!(exp /= 2))break;
		(base_ *= base_).mod(m);
	}
	return res;
}
class unionfind {
	vector<int> par, rank, size_;//????????§??????????????¢???????????????????????????rank???????????????size?????????
public:
	unionfind(int n) :par(n), rank(n), size_(n, 1) {
		iota(ALL(par), 0);
	}
	int find(int x) {
		if (par[x] == x)return x;
		return par[x] = find(par[x]);
	}
	void unite(int x, int y) {
		x = find(x), y = find(y);
		if (x == y)return;
		if (rank[x] < rank[y])swap(x, y);
		par[y] = x;
		size_[x] += size_[y];
		if (rank[x] == rank[y])rank[x]++;
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
	int size(int x) {
		return size_[find(x)];
	}
};
//end of lib
//template<class S=void,int ptr_num, class T = char>class trie {
//	umap<T, trie<S, ptr_num, T> next;
//public:
//	S key;
//	trie<S, ptr_num, T>* ptr[ptr_num] = {};
//	trie(S &&data) :key(data) {}
//	trie(const S &data) :key(data) {}
//	void add(T x,S data) {
//		if (!next.find(x))next.insert(x, data);
//	}
//	trie& operator[](T x) {
//		return next[x];
//	}
//	bool find(T x) {
//		retun next.find(x);
//	}
//};
//template<class T=char>class AhoCorasick {
//	trie<pair<bool,int>, 2, T> tree;
//	AhoCorasick(vector<string> p) {
//		int num = 0;
//		vector<decltype(&tree)> que(p.size(),&tree);
//		for (int i = 0;; i++) {
//			bool end = 1;
//			int i = 0;
//			for (auto a : p) {
//				if (i >= a.size())break;
//				end = ;0
//				que[i] = (*que[i])[a[i]];
//				i++;
//			}
//			if (end)break;
//		}
//	}
//};
using namespace std;

struct state{
	vi kizoku;
	array<vi,3> action;
};
array<int, 3> f(state s,int p) {
	if (s.kizoku.empty())return{ 0,0,0 };
	auto s2 = s;
	s2.kizoku.erase(s2.kizoku.begin());
	auto ret = f(s2, (p + 1) % 3);
	ret[p] += s.kizoku.front();
	rep(i, s.action[p].size()) {
		if (s.action[p][i] > s.kizoku.size())continue;
		s2 = s;
		s2.action[p].erase(s2.action[p].begin() + i);
		s2.kizoku.erase(s2.kizoku.begin() + s.action[p][i] - 1);
		auto ret2 = f(s2, (p + 1) % 3);
		ret2[p] += s.kizoku[s.action[p][i] - 1];
		if (ret2[p] > ret[p])ret = ret2;
	}
	return ret;
}
array<int, 3> f2(state s, int p) {
	if (s.kizoku.empty())return{ 0,0,0 };
	auto s2 = s;
	s2.kizoku.erase(s2.kizoku.begin());
	auto sm = s2;
	if (p == 1) {
		auto ret = f2(s2, (p + 1) % 3);
		ret[p] += s.kizoku.front();
		rep(i, s.action[p].size()) {
			if (s.action[p][i] > s.kizoku.size())continue;
			s2 = s;
			s2.action[p].erase(s2.action[p].begin() + i);
			s2.kizoku.erase(s2.kizoku.begin() + s.action[p][i] - 1);
			auto ret2 = f2(s2, (p + 1) % 3);
			ret2[p] += s.kizoku[s.action[p][i] - 1];
			if (ret2[0]<ret[0])ret = ret2, sm = s2;
		}
		return ret;
	}
	auto ret = f(s2, (p + 1) % 3);
	int plus;
	ret[p] += plus = s.kizoku.front();
	rep(i, s.action[p].size()) {
		if (s.action[p][i] > s.kizoku.size())continue;
		s2 = s;
		s2.action[p].erase(s2.action[p].begin() + i);
		s2.kizoku.erase(s2.kizoku.begin() + s.action[p][i] - 1);
		auto ret2 = f(s2, (p + 1) % 3);
		ret2[p] += s.kizoku[s.action[p][i] - 1];
		if (ret2[p] > ret[p])ret = ret2, sm = s2, plus = s.kizoku[s.action[p][i] - 1];
	}
	ret= f2(sm, (p + 1) % 3);
	ret[p] += plus;
	return ret;
}


int main() {
	state s;
	s.kizoku.resize(12);
	rrep(i, 12)cin >> s.kizoku[i];
	rep(i, 3) {
		s.action[i].resize(2);
		rep(j, 2)cin >> s.action[i][j];
		sort(ALL(s.action[i]));
	}
	auto ret = f2(s, 0);
	cout << ret[0] << " " << ret[1] << " " << ret[2] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3148
final_rank: 2

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class t>
using table = vector<vector<t>>;
const ld eps = 1e-9;

//// < "d:\d_download\visual studio 2015\projects\programing_contest_c++\debug\a.txt" > "d:\d_download\visual studio 2015\projects\programing_contest_c++\debug\b.txt"
  

vector<int>nobles(12);
vector<vector<int>>cards(3, vector<int>(2));


struct result {
	bool isini;
	vector<int>scores;
	vector<vector<int>>used;
	result() :isini(true),scores(), used() {

	}
	result(const vector<int>&scores_, const vector<vector<int>>&used_):isini(false),scores(scores_),used(used_) {

	}
	
};
bool compare(const result&l, const result&r,const int now,const bool kappathink) {
	if (l.isini)return true;
	else {
		if (now == 1&&kappathink) {
			if (l.scores[0] < r.scores[0])return false;
			else if (l.scores[0]>r.scores[0])return true;
		}
		else {
			if (l.scores[now] < r.scores[now])return true;
			else if (l.scores[now]>r.scores[now])return false;
		}
		int luse=0, ruse=0, ltotal=0, rtotal=0;
		for (int i = 0; i < 2; ++i) {
			if (l.used[now][i]) {
				luse++;
				ltotal += cards[now][i];
			}
			if (r.used[now][i]) {
				ruse++;
				rtotal += cards[now][i];
			}
		}
		return luse == ruse ? ltotal < rtotal : luse < ruse;
	}
}
result memo[4096][64][3][2];

int getnum(const bitset<12>&v, int num) {
	for (int i = 11; i >= 0; --i) {
		if (v[i]) {
			num--;
			if (!num)return  i;
		}
	}
	return -1;
}

int gethash(const vector<vector<int>>&vs) {
	int num = 0;
	for (int i = 0; i < 3; ++i) {
		for (int j = 0; j < 2; ++j) {
			num *= 2;
			if (vs[i][j])num++;
		}
	}
	return num;
}

result getans(const int now, vector<vector<int>>&used, bitset<12>&lives,bool kappathink) {
	if (!memo[lives.to_ulong()][gethash(used)][now][kappathink].isini)return memo[lives.to_ulong()][gethash(used)][now][kappathink];
	
	if (!lives.count()) {
		return memo[lives.to_ulong()][gethash(used)][now][kappathink]=result{ vector<int>(3,0),used };
	}
	else {
		result nowres;
		result nowrealres;
		{
			vector<int>scores(3);

			const int pl = getnum(lives, 1);
			assert(pl != -1);
			{
				assert(lives[pl]);
				lives[pl] = false;
				result res = getans((now + 1) % 3, used, lives, kappathink&&(now == 1));
				result realres = getans((now + 1) % 3, used, lives, kappathink);
				lives[pl] = true;
				res.scores[now] += nobles[pl];
				realres.scores[now] += nobles[pl];
				if (compare(nowres, res, now, kappathink)) {
					nowres = res;
					nowrealres = realres;
				}
			}
		}
		for (int i = 0; i < 2; ++i) {
			if (used[now][i]) {
				used[now][i] = false;
				int pl = getnum(lives, cards[now][i]);
				if (pl == -1) {
					pl = getnum(lives, 1);
				}
				{
					assert(pl != -1);
					assert(lives[pl]);
					lives[pl] = false;
					result res = getans((now + 1) % 3, used, lives, kappathink&&(now == 1));
					result realres = getans((now + 1) % 3, used, lives, kappathink);
					lives[pl] = true;
					res.scores[now] += nobles[pl];
					realres.scores[now] += nobles[pl];
					if (compare(nowres, res, now, kappathink)) {
						nowres = res;
						nowrealres = realres;
					}
				}
				used[now][i] = true;
			}
		}
		return memo[lives.to_ulong()][gethash(used)][now][kappathink] = nowrealres;
	}
}

int main() {
	for (int i = 0; i < 4096; ++i) {
		for (int j = 0; j < 64; ++j) {
			for (int k = 0; k < 3; ++k) {
				for (int l = 0; l < 2; ++l) {
					memo[i][j][k][l] = result();
				}
			}
		}
	}
	for (int i = 0; i < 12; ++i)cin >> nobles[i];
	for (int i = 0; i < 3; ++i) {
		for (int j = 0; j < 2; ++j) {
			cin >> cards[i][j];
		}
	}

	vector<vector<int>>used(3, vector<int>(2,1));
	bitset<12>bs((1<<12)-1);
	result ans = getans(0, used, bs, true);
	cout << ans.scores[0] << " "<<ans.scores[1]<<" " << ans.scores[2] << endl;

	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 90216
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
typedef vector<int> vi;
typedef array<vi,3> typeA;
struct State{
	vi xs;
	typeA as;
	int turn;
	bool operator <(const State& st) const {
		if(xs!=st.xs) return xs<st.xs;
		if(as!=st.as) return as<st.as;
		return turn<st.turn;
	}
};
void showstate(State st){
	cout<<"xs:   ";
	for(int x:st.xs) cout<<x<<" ";
	puts("");
}
map<State,vi> mp,asmp;
map<State,State> nxtstate;		//0,2?????¨???
map<State,vi> tscore;			//state->nxtstate???????????°??????
vi asp(State st){
//	showstate(st);
	if(asmp.count(st)) return asmp[st];
	if(st.xs.empty()) return asmp[st]=vi(3,0);
	vi xs=st.xs;
	typeA as=st.as;
	int t=st.turn;
	vi best;
	State nxt_;
	vi tsc_(3,0);
	rep(i,3){
		if(i==t) best.pb(-100);
		else best.pb(100);
	}
	//dont action
	{
		int p=xs[0];
		vi nxs=xs;
		nxs.erase(nxs.begin());
		typeA nas=as;
		int nt=(t+1)%3;
		State nst={nxs,nas,nt};
		vi ps=asp(nst);
		ps[t]+=p;
		if(best[t]<ps[t]){
			best=ps;
			nxt_=nst;
			tsc_[t]=p;
		}
	}
	//action
	rep(i,as[t].size()){
		int y=as[t][i];
		if(xs.size()<=y) continue;
		int p=xs[y];
		vi nxs=xs;
		nxs.erase(nxs.begin()+y);
		typeA nas=as;
		nas[t].erase(nas[t].begin()+i);
		int nt=(t+1)%3;
		State nst={nxs,nas,nt};
		vi ps=asp(nst);
		ps[t]+=p;
		if(best[t]<ps[t]){
			best=ps;
			nxt_=nst;
			tsc_[t]=p;
		}
	}
	nxtstate[st]=nxt_;
	tscore[st]=tsc_;
	return asmp[st]=best;
}
pair<State,vi> nextkappa(State st){
	vi ret(3,0);
	asp(st);
	rep(i,3) ret[i]+=tscore[st][i];
	st=nxtstate[st];
	rep(i,3) ret[i]+=tscore[st][i];
	st=nxtstate[st];
	return pair<State,vi>(st,ret);
}
vi getp(State st){
	if(mp.count(st)) return mp[st];
	vi xs=st.xs;
	typeA as=st.as;
	int t=st.turn;
	if(xs.size()==2){
		vi nscore;
		nscore.pb(0);
		nscore.pb(xs[0]);
		nscore.pb(xs[1]);
		return mp[st]=nscore;
	}
	vi best;
	rep(i,3){
		if(i==t) best.pb(-100);
		else best.pb(100);
	}
	//dont action
	{
		int p=xs[0];
		vi nxs=xs;
		nxs.erase(nxs.begin());
		typeA nas=as;
		int nt=(t+1)%3;
		State nst{nxs,nas,nt};
		//minimize 0
		pair<State,vi> Pst=nextkappa(nst);
		State nxtK=Pst.fs;
		vi tmpscore=Pst.sc;
		vi ps=getp(nxtK);
		ps[t]+=p;
		rep(j,3) ps[j]+=tmpscore[j];
		if(best[0]>ps[0]) best=ps;
	}
	//action
	rep(i,as[t].size()){
		int y=as[t][i];
		if(xs.size()<=y) continue;
		int p=xs[y];
		vi nxs=xs;
		nxs.erase(nxs.begin()+y);
		typeA nas=as;
		nas[t].erase(nas[t].begin()+i);
		int nt=(t+1)%3;
		State nst={nxs,nas,nt};
		//minimize 0
		pair<State,vi> Pst=nextkappa(nst);
		State nxtK=Pst.fs;
		vi tmpscore=Pst.sc;
		vi ps=getp(nxtK);
		ps[t]+=p;
		rep(j,3) ps[j]+=tmpscore[j];
		if(best[0]>ps[0]) best=ps;
	}
	return mp[st]=best;
}

int main(){
	vector<int> xs;
	rep(i,12){
		int x;
		cin>>x;
		xs.pb(x);
	}
	reverse(all(xs));
	typeA as;
	rep(i,3){
		int aa,aaa;
		cin>>aa>>aaa;
		as[i].pb(aa-1);
		as[i].pb(aaa-1);
		sort(all(as[i]));
	}
	State be={xs,as,0};
	asp(be);
	vi fscore=tscore[be];
	be=nxtstate[be];
//	showstate(be);
	vi ans=getp(be);
	ans[0]+=fscore[0];
	cout<<ans[0]<<" "<<ans[1]<<" "<<ans[2]<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 2852
final_rank: 1