Submission #1244393

#TimeUsernameProblemLanguageResultExecution timeMemory
1244393errayHieroglyphs (IOI24_hieroglyphs)C++20
0 / 100
1093 ms13128 KiB
#include <bits/stdc++.h>
#include <vector>
#include "hieroglyphs.h"
using namespace std;

#ifdef DEBUG
	#include "debug.h"
#else
	#define debug(...) void(37)
#endif

template<typename T> bool cmax(T& x, T y) { 
	if (y > x) {
		x = y;
		return true;
	}
	return false;
};

template<typename T> bool cmin(T& x, T y) {
	if (y < x) {
		x = y;
		return true;
	}
	return false;
}

constexpr int MAX = int(2e5) + 1;

vector<int> find_boundaries(vector<int> a, vector<int> b) {
	int n = int(a.size()), m = int(b.size());
	vector<int> occ_diff(MAX);
	for (auto x : a) occ_diff[x]++;
	for (auto x : b) occ_diff[x]--;
	vector<bool> mine(MAX);
	for (int i = 0; i < MAX; ++i) {
		if (occ_diff[i] <= 0) mine[i] = true;
	}
	vector<vector<int>> pos(MAX);
	for (int i = 0; i < m; ++i) pos[b[i]].push_back(i);
	vector<int> first_sub(n, m + 1);
	for (int i = 0; i < n; ++i) {
		if(!mine[a[i]]) continue;
		auto& v = pos[a[i]];
		int len = int(v.size());
		int x = m + 1;
		int j = i - 1;
		for (j = i - 1; j >= 0; --j) {
			cmin(x, first_sub[j]);
			if (a[i] == a[j]) break;
		}
		if (j == -1) x = -1;
		int next_ind = int(lower_bound(v.begin(), v.end(), x + 1) - v.begin());
		assert(next_ind < len);
		first_sub[i] = v[next_ind];				
	}
	vector<bool> after_me(MAX);
	vector<int> previous_to(n, m + 1);
	for (int i = n - 1; i >= 0; --i) {
		if (!mine[a[i]]) after_me[a[i]] = true;
		else {
			int j = first_sub[i];
			while (j < m && !(after_me[b[j]] && pos[b[j]].back() == j)) ++j;
			previous_to[i] = j;
		}
	}
	return previous_to;
}

std::vector<int> ucs(std::vector<int> A, std::vector<int> B) {
	int N = int(A.size()), M = int(B.size());
	vector<int> occ_A(MAX), occ_B(MAX);
	debug(A, B);
	for (auto x : A) occ_A[x]++;
	for (auto x : B) occ_B[x]++;
	int req_len = 0;
	for (int i = 0; i < MAX; ++i) {
		req_len += min(occ_A[i], occ_B[i]);
	}
	auto previous_to_A = find_boundaries(A, B);
	auto previous_to_B = find_boundaries(B, A);

	debug(previous_to_A);
	debug(previous_to_B);
	vector<vector<int>> longest(N + 1, vector<int>(M + 1));
	vector<vector<int>> from(N + 1, vector<int>(M + 1, -1));
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < M; ++j) {
			if (A[i] == B[j] && previous_to_A[i] > j && previous_to_B[j] > i && cmax(longest[i + 1][j + 1], longest[i][j] + 1)) {
				from[i + 1][j + 1] = 3;
			}
			if (cmax(longest[i + 1][j], longest[i][j])) {
				from[i + 1][j] = 1;
			}
			if (cmax(longest[i][j + 1], longest[i][j])) {
				from[i][j + 1] = 2;
			}
		}
	}
	if (req_len != longest[N][M]) {
		return {-1};
	} else {
		vector<int> ans;
		{
			int i = N, j = M;
			while (int(ans.size()) < req_len) {
				int to = from[i][j];
				i -= to & 1;
				j -= (to >> 1) & 1;
				if (to == 3) {
					ans.push_back(A[i]);
				}
			}
		}
		reverse(ans.begin(), ans.end());
		return ans;
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...