#include "friend.h"
#include "bits/stdc++.h"
using namespace std;
#define sz(x) (int)(x.size())
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<pii> vpii;
void dfs(int v, int p, vvi &adj, vvi &mxt, const int C[])
{
	mxt[v][1] = C[v];
	for (int u : adj[v])
	{
		if (u == p)
			continue;
		dfs(u, v, adj, mxt, C);
		mxt[v][0] += max(mxt[u][0], mxt[u][1]);
		mxt[v][1] += mxt[u][0];
	}
}
// Find out best sample
int findSample(int n, int confidence[], int host[], int protocol[])
{
	if (n <= 20)
	{
		vi forbidden;
		vvi adj(n);
		for (int t = 1; t < n; ++t)
		{
			int h = host[t];
			if (protocol[t] == 0 || protocol[t] == 2) // I & We
			{
				adj[h].push_back(t), adj[t].push_back(h);
				forbidden.push_back((1 << h) + (1 << t));
			}
			if (protocol[t] == 1 || protocol[t] == 2) // My & We
				for (int u : adj[h])
				{
					adj[u].push_back(t), adj[t].push_back(u);
					forbidden.push_back((1 << u) + (1 << t));
				}
		}
		int maxres = 0;
		for (int bitmask = 0; bitmask < (1 << n); ++bitmask)
		{
			bool bad = false;
			for (int f : forbidden)
				if ((f & bitmask) == f)
				{
					bad = true;
					break;
				}
			if (bad)
				continue;
			int res = 0;
			for (int i = 0; i < n; ++i)
				if (bitmask & (1 << i))
					res += confidence[i];
			maxres = max(res, maxres);
		}
		return maxres;
	}
	vi C(n);
	// copy(confidence, confidence + n, C.begin());
	// subtaks 2: only my friends are your friends -> independent set!
	// int sum = accumulate(confidence, confidence + n, 0);
	// subtask 3: only we are your friends -> complete graph
	// int maxi = *max_element(confidence, confidence + n);
	// subtask 4: only I am your friend -> tree dp
	/*
	vvi adj(n);
	for (int t = 1; t < n; ++t)
	{
		adj[host[t]].push_back(t);
		adj[t].push_back(host[t]);
	}
	vvi max_subtree(n, vi(2, 0)); // max subtree without and with corresponding root
	dfs(0, 0, adj, max_subtree, confidence);
	return max(max_subtree[0][0], max_subtree[0][1]);
	*/
	vi sols;
	vvi solutions;
	vvi dp(n, vi(2, 0)); // should point to the solution in the above vectors
	dp[0][0] = 0;		 // best res without node 0
	dp[0][1] = 1;		 // best rest with node 0
	sols.push_back(0);
	solutions.push_back(vi());
	sols.push_back(confidence[0]);
	solutions.push_back(vi(1, 0));
	int bestSolSoFar = 1;
	for (int t = 1; t < n; ++t)
	{
		int h = host[t];
		assert(h < t);
		int op = protocol[t];
		dp[t][0] = bestSolSoFar;
		int refsol;
		if (op == 0)
		{
			// I
			refsol = dp[h][0];
		}
		else if (op == 1)
		{
			// My
			refsol = dp[h][1];
		}
		else if (op == 2)
		{
			// We
			assert(false);
		}
		else
		{
			assert(false);
		}
		int solidx = sz(solutions);
		vi members;
		sols.push_back(confidence[t] + sols[refsol]);
		members = vi(solutions[refsol].begin(), solutions[refsol].end());
		members.push_back(t);
		solutions.push_back(members);
		for (int i = 0; i < sz(members) - 1; ++i)
		{
			if (sols[dp[members[i]][1]] < sols[solidx])
				dp[members[i]][1] = solidx;
			assert(members[i] < members[i + 1]);
			for (int j = members[i] + 1; j < members[i + 1]; ++j)
			{
				if (sols[dp[j][0]] < sols[solidx])
					dp[j][0] = solidx;
			}
		}
		dp[t][1] = solidx; // last member is t itself
		if (sols[solidx] > bestSolSoFar)
			bestSolSoFar = solidx;
	}
	return sols[bestSolSoFar];
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |