Problem:
Score : 600 points

Problem Statement

We have 3N cards arranged in a row from left to right, where each card has an integer between 1 and N (inclusive) written on it. The integer written on the i-th card from the left is A_i.

You will do the following operation N-1 times:

Rearrange the five leftmost cards in any order you like, then remove the three leftmost cards. If the integers written on those three cards are all equal, you gain 1 point.

After these N-1 operations, if the integers written on the remaining three cards are all equal, you will gain 1 additional point.

Find the maximum number of points you can gain.

Constraints

1 \leq N \leq 2000

1 \leq A_i \leq N

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 \cdots A_{3N}

Output

Print the maximum number of points you can gain.

Sample Input 1

2
1 2 1 2 2 1

Sample Output 1

2

Let us rearrange the five leftmost cards so that the integers written on the six cards will be 2\ 2\ 2\ 1\ 1\ 1 from left to right.

Then, remove the three leftmost cards, all of which have the same integer 2, gaining 1 point.

Now, the integers written on the remaining cards are 1\ 1\ 1.

Since these three cards have the same integer 1, we gain 1 more point.

In this way, we can gain 2 points - which is the maximum possible.

Sample Input 2

3
1 1 2 2 3 3 3 2 1

Sample Output 2

1

Sample Input 3

3
1 1 2 2 2 3 3 3 1

Sample Output 3

3

Solution in C++ (GCC 9.2.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef	long long ll;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef set<int> si;
typedef map<int,int> mii;
typedef map<ll,ll> mll;
typedef vector<pii> vii;
typedef vector<pll> vll;
typedef pair<ll, pll> plll;
typedef vector<pair<int, pii>> viii;
#define fi first
#define se second
#define pi 3.141592653589793
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define all(v) v.begin(),v.end()
#define tc int tt;cin>>tt;while(tt--)
#define pqmax priority_queue<int>
#define pqmin priority_queue<int,vi,greater<int>>
#define fio ios_base::sync_with_stdio(0), cin.tie(NULL)
#define tc_g int tt;cin>>tt;for(int ti=1;ti<=tt;ti++)
#define case_g "Case #"<<ti<<": "
#define RED "\033[31m"
#define GREEN "\033[32m"
#define RESET "\033[0m"
#define sleep for (int i = 1, a;i < 100000000;i++, a = a * a)
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> ranked_pairset;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ranked_set;
typedef tree<int, int, less<int>, rb_tree_tag, tree_order_statistics_node_update> ranked_map;

int dp[2001][2001];

int main() {
	fio;
	int n;
	cin >> n;
	int a[3 * n];
	for (int i = 0;i < 3 * n;i++)
		cin >> a[i];
	int extra = 0;
	bool p[n + 1] = {};
	for (int i = 1;i <= n;i++)
		for (int j = i;j <= n;j++)
			dp[i][j] = INT32_MIN;
	sort(a, a + 2);
	dp[a[0]][a[1]] = 0;
	p[a[0]] = 1;
	p[a[1]] = 1;
	for (int i = 2;i < 3 * n - 3;i += 3) {
		
		//for (int x = 1;x <= n;x++)
			//for (int y = x;y <= n;y++) {
				//cout << x << ' ' << y << " - ";
				//if (dp[x][y] == INT32_MIN)
					//cout << "!\n";
				//else
					//cout << dp[x][y] + extra << '\n';
			//}
		//cout << '\n';
		
		sort(a + i, a + i + 3);
		
		vector<pair<pii, int>> upd;
		
		for (int j = i;j < i + 3;j++)
			if (dp[a[j]][a[j]] != INT32_MIN) {
				int x = (j + 1 >= i + 3 ? j - 2 : j + 1);
				int y = (j + 2 >= i + 3 ? j - 1 : j + 2);
				upd.pb({{a[x], a[y]}, dp[a[j]][a[j]] + 1});
			}
		
		for (int j = i;j < i + 3;j++) {
			if (p[a[j]]) {
				if (dp[a[j]][a[j]] == INT32_MIN)
					upd.pb({{a[j], a[j]}, -extra});
			}
			else {
				for (int k = 1;k <= n;k++)
					if (p[k] && dp[min(k, a[j])][max(k, a[j])] == INT32_MIN)
						upd.pb({{k, a[j]}, -extra});
				p[a[j]] = 1;
			}
		}
		
		if (a[i] == a[i + 1]) {
			for (int k = 1;k <= n;k++)
				if (dp[min(a[i], k)][max(a[i], k)] != INT32_MIN)
					upd.pb({{k, a[i + 2]}, dp[min(a[i], k)][max(a[i], k)] + 1});
		}
		else if (a[i + 1] == a[i + 2]) {
			for (int k = 1;k <= n;k++)
				if (dp[min(a[i + 1], k)][max(a[i + 1], k)] != INT32_MIN)
					upd.pb({{k, a[i]}, dp[min(a[i + 1], k)][max(a[i + 1], k)] + 1});
		}
		for (auto x : upd)
			dp[min(x.fi.fi, x.fi.se)][max(x.fi.fi, x.fi.se)] = max(dp[min(x.fi.fi, x.fi.se)][max(x.fi.fi, x.fi.se)], x.se - (a[i] == a[i + 1] && a[i] == a[i + 2]));
		if (a[i] == a[i + 1] && a[i] == a[i + 2])
			extra++;
	}
	
	//for (int x = 1;x <= n;x++)
		//for (int y = x;y <= n;y++) {
			//cout << x << ' ' << y << " - ";
			//if (dp[x][y] == INT32_MIN)
				//cout << "!\n";
			//else
				//cout << dp[x][y] + extra<< '\n';
		//}
	//cout << '\n';
	
	if (dp[a[3 * n - 1]][a[3 *n - 1]] != INT32_MIN)
		dp[a[3 * n - 1]][a[3 *n - 1]]++;
	
	//for (int x = 1;x <= n;x++)
		//for (int y = x;y <= n;y++) {
			//cout << x << ' ' << y << " - ";
			//if (dp[x][y] == INT32_MIN)
				//cout << "!\n";
			//else
				//cout << dp[x][y] + extra<< '\n';
		//}
	//cout << '\n';
	
	int ans = INT32_MIN;
	for (int i = 1;i <= n;i++)
		for (int j = i;j <= n;j++)
			ans = max(ans, dp[i][j]);
	cout << ans + extra << '\n';
}