Submission #1001094

#TimeUsernameProblemLanguageResultExecution timeMemory
1001094vuavisaoSeptember (APIO24_september)C++17
100 / 100
248 ms47304 KiB
#include "september.h" #include <vector> #include <bits/stdc++.h> using namespace std; using ll = long long; const int N = 100'000 + 10; const int INF = 1'000'000'000; struct FenWick { int n_node = 0; vector<int> tree; void resize(int n) { n_node = n; vector<int>().swap(tree); tree.resize(n_node + 10, 0); } FenWick() {}; FenWick(int n) { this->resize(n); }; void Update(int idx, int val) { for ( ; idx <= n_node; idx += (idx & - idx)) tree[idx] += val; return; } int Query(int idx) { int res = 0; for ( ; idx > 0; idx -= (idx & - idx)) res += tree[idx]; return res; } int Sum_to(int l, int r) { if (l > r) return 0; return Query(r) - Query(l - 1); } int kth(int val) { int res = 0, s = 0; for (int mask = 30; mask >= 0; -- mask) { int nxt = res | (1 << mask); if (nxt < n_node && s + tree[nxt] < val) { res = nxt; s += tree[nxt]; } } ++ res; return res; } }; struct FenWickMax { int n_node = 0; vector<int> tree; void resize(int n) { n_node = n; vector<int>().swap(tree); tree.resize(n_node + 10, -INF); } FenWickMax() {}; FenWickMax(int n) { this->resize(n); }; void Update(int idx, int val) { for ( ; idx > 0; idx -= (idx & - idx)) tree[idx] = max(tree[idx], val); return; } int Query(int idx) { int res = -INF; for ( ; idx <= n_node; idx += (idx & - idx)) res = max(res, tree[idx]); return res; } }; int n, m; int parent[N]; vector<int> g[N]; int perRem[10][N]; int need[10][N]; namespace Order { int indexing[N]; void dfs(int u, int res[]) { int idx = indexing[u]; res[idx] = idx; for (const auto& v : g[u]) { dfs(v, res); res[idx] = max(res[idx], res[indexing[v]]); } } void solve(int perRem[], int res[]) { for (int i = 1; i < n; ++ i) { indexing[perRem[i]] = i; } indexing[1] = 0; dfs(1, res); } } namespace One { bool check() { return (m == 1); } vector<int> open[N]; int dp[N]; int solve() { for (int i = 0; i <= n + 1; ++ i) { vector<int>().swap(open[i]); dp[i] = -INF; } for (int i = 1; i < n; ++ i) { open[need[1][i]].push_back(i); } dp[0] = 0; FenWick bit(n); for (int i = 1; i < n; ++ i) bit.Update(i, 1); FenWickMax bitMax(n); for (int i = 1; i < n; ++ i) { for (const auto& idx : open[i]) bit.Update(idx, -1); bitMax.Update(i, dp[i - 1]); int cnt = bit.Query(i); int last = bit.kth(cnt) + (cnt != 0); if (last <= i) { dp[i] = bitMax.Query(last) + 1; } } return dp[n - 1]; } } namespace Brute_force { bool check() { return (n <= 1'000); } unsigned seed = chrono::system_clock::now().time_since_epoch().count(); mt19937_64 rng(seed); ll Rand(ll a, ll b = 1ll * INF * INF) { return a + rng() % (b - a + 1); } bool can[1'010][1'010]; ll base[N]; ll Hash[10][N]; vector<int> open[N]; int exist[N]; int dp[N]; int solve() { srand(time(nullptr)); for (int i = 0; i <= n + 1; ++ i) { dp[i] = -INF; exist[i] = 0; vector<int>().swap(open[i]); } for (int i = 0; i <= n + 1; ++ i) { for (int j = 0; j <= n + 1; ++ j) { can[i][j] = false; } } for (int i = 1; i <= n; ++ i) base[i] = Rand(1); for (int i = 1; i <= m; ++ i) { for (int j = 1; j < n; ++ j) { Hash[i][j] = base[perRem[i][j]]; open[need[i][j]].push_back(j); } } for (int i = 1; i < n; ++ i) { ll xorHash[6]; memset(xorHash, 0, sizeof(xorHash)); for (int j = i; j < n; ++ j) { for (int k = 1; k <= m; ++ k) { xorHash[k] ^= Hash[k][j]; } if (*min_element(xorHash + 1, xorHash + 1 + m) == *max_element(xorHash + 1, xorHash + 1 + m)) { can[i][j] = true; } } } dp[0] = 0; for (int i = 1; i < n; ++ i) { for (const auto& idx : open[i]) ++ exist[idx]; for (int j = i; j >= 1; -- j) { if (exist[j] < m) break; if (can[j][i]) { // cout << j << ' ' << i << ' ' << dp[i] << ' ' << dp[j - 1] << '\n'; dp[i] = max(dp[i], dp[j - 1] + 1); } } } return dp[n - 1]; } } namespace Full { int L[N], R[N]; int pred[N]; vector<int> position[N]; int indexing[N]; vector<int> open[N]; int exist[N]; FenWickMax bitMax[N]; int dp[N]; int solve() { for (int i = 0; i <= n + 1; ++ i) { position[i].clear(); pred[i] = 0; L[i] = n + 1; R[i] = 0; dp[i] = -INF; exist[i] = 0; vector<int>().swap(open[i]); } for (int i = 1; i <= m; ++ i) { for (int j = 1; j < n; ++ j) { int u = perRem[i][j]; L[u] = min(L[u], j); R[u] = max(R[u], j); open[need[i][j]].push_back(j); } } for (int u = 2; u <= n; ++ u) { ++ pred[L[u]]; -- pred[R[u]]; } for (int i = 1; i < n; ++ i) { pred[i] += pred[i - 1]; position[pred[i - 1]].push_back(i - 1); indexing[i - 1] = position[pred[i - 1]].size(); } FenWick bit(n); for (int i = 1; i < n; ++ i) bit.Update(i, m); for (int i = 0; i < n; ++ i) { if (position[i].empty()) continue; bitMax[i].resize(position[i].size()); } dp[0] = 0; for (int i = 1; i < n; ++ i) { for (const auto& idx : open[i]) { bit.Update(idx, -1); if (++ exist[idx] == m) { int newIndex = idx - 1; assert(newIndex < i); int group = pred[newIndex]; bitMax[group].Update(indexing[newIndex], dp[newIndex]); } } int group = pred[i]; if (position[group].empty()) continue; int cnt = bit.Query(i); int last = bit.kth(cnt) - (cnt == 0); auto ptr = lower_bound(position[group].begin(), position[group].end(), last); if (ptr != position[group].end()) { int idx = position[group][ptr - position[group].begin()]; dp[i] = bitMax[group].Query(indexing[idx]) + 1; } } return dp[n - 1]; } } int solve(int N, int M, std::vector<int> F, std::vector<std::vector<int>> S) { n = N; m = M; for (int i = 0; i <= n + 1; ++ i) g[i].clear(); for (int v = 2; v <= n; ++ v) { int u = F[v - 1] + 1; g[u].push_back(v); parent[v] = u; } for (int i = 0; i < m; ++ i) { for (int j = 0; j < n - 1; ++ j) { perRem[i + 1][j + 1] = S[i][j] + 1; } } for (int i = 1; i <= m; ++ i) { Order::solve(perRem[i], need[i]); } if (One::check()) { return One::solve(); } if (Brute_force::check()) { return Brute_force::solve(); } return Full::solve(); }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...