Submission #1009848

#TimeUsernameProblemLanguageResultExecution timeMemory
1009848boris_mihovClosing Time (IOI23_closing)C++17
83 / 100
1024 ms974124 KiB
#include "closing.h" #include <algorithm> #include <iostream> #include <numeric> #include <cassert> #include <vector> #include <queue> typedef long long llong; const int MAXN2 = 200000 + 10; const int MAXN = 3000 + 10; const llong INF = 8e18; const int INTINF = 2e9; int n; int x; int y; llong k; int sz[MAXN]; int par[MAXN]; bool isOnPath[MAXN]; std::vector <int> path; std::vector <int> pathSizes; std::vector <std::pair <int,int>> g[MAXN2]; std::vector <int> suffixSizes[MAXN]; llong dpR[MAXN][2 * MAXN][2][2]; // root llong dpC[MAXN][2 * MAXN][2][2]; // children, knapsack llong dpS[MAXN][2 * MAXN][2][2]; // stick bool blR[MAXN][2 * MAXN][2][2]; bool blC[MAXN][2 * MAXN][2][2]; bool blS[MAXN][2 * MAXN][2][2]; llong distX[MAXN2]; llong distY[MAXN2]; bool disjoint; void reset() { path.clear(); pathSizes.clear(); for (int i = 0 ; i < n ; ++i) { g[i].clear(); distX[i] = distY[i] = 0; if (disjoint) { continue; } suffixSizes[i].clear(); isOnPath[i] = false; for (int j = 0 ; j <= 2 * n ; ++j) { for (int flagX = 0 ; flagX < 2 ; ++flagX) { for (int flagY = 0 ; flagY < 2 ; ++flagY) { dpR[i][j][flagX][flagY] = 0; dpC[i][j][flagX][flagY] = 0; dpS[i][j][flagX][flagY] = 0; blR[i][j][flagX][flagY] = false; blC[i][j][flagX][flagY] = false; blS[i][j][flagX][flagY] = false; } } } } } void dfs(int node, int par, llong to[], llong dist) { to[node] = dist; for (const auto &[u, d] : g[node]) { if (u == par) { continue; } dfs(u, node, to, dist + d); } } bool dfsPath(int node, int par) { if (node == y) { path.push_back(node); return true; } for (const auto &[u, d] : g[node]) { if (u == par) { continue; } if (dfsPath(u, node)) { path.push_back(node); return true; } } return false; } void dfsSize(int node, int p) { sz[node] = 1; par[node] = p; for (const auto &[u, d] : g[node]) { if (p == u) { continue; } dfsSize(u, node); if (!isOnPath[u]) sz[node] += sz[u]; } } llong fRoot(int, int, int, int); llong fChildren(int, int, int, int, int); llong fStick(int, int, int, int); llong fRoot(int node, int choose, int flagX, int flagY) { if (choose == 0) { return 0; } if (!flagX && !flagY) { return k + 1; } if (blR[node][choose][flagX][flagY]) { return dpR[node][choose][flagX][flagY]; } blR[node][choose][flagX][flagY] = true; dpR[node][choose][flagX][flagY] = fChildren(node, 0, choose, flagX, flagY); dpR[node][choose][flagX][flagY] = std::min(dpR[node][choose][flagX][flagY], k + 1); return dpR[node][choose][flagX][flagY]; } llong fChildren(int node, int idx, int choose, int flagX, int flagY) { if (choose == 0) { return 0; } if (idx == g[node].size()) { if (choose == 0) return 0; return k + 1; } int current = g[node][idx].first; if (isOnPath[current] || current == par[node]) { return fChildren(node, idx + 1, choose, flagX, flagY); } if (blC[current][choose][flagX][flagY]) { return dpC[current][choose][flagX][flagY]; } blC[current][choose][flagX][flagY] = true; dpC[current][choose][flagX][flagY] = k + 1; for (int currX = 0 ; currX <= flagX ; ++currX) { for (int currY = 0 ; currY <= flagY ; ++currY) { for (int subtreeChoose = std::max(choose - (flagX + flagY) * suffixSizes[node][idx + 1], currX + currY) ; subtreeChoose <= std::min((currX + currY) * sz[g[node][idx].first], choose) ; ++subtreeChoose) { dpC[current][choose][flagX][flagY] = std::min(dpC[current][choose][flagX][flagY], fChildren(node, idx + 1, choose - subtreeChoose, flagX, flagY) + std::max((currX == 0 ? 0 : distX[current]), (currY == 0 ? 0 : distY[current])) + fRoot(current, subtreeChoose - currX - currY, currX, currY)); } } } return dpC[current][choose][flagX][flagY]; } llong fStick(int idx, int choose, int flagX, int flagY) { if (idx == path.size()) { if (choose == 0) return 0; return k + 1; } if (blS[idx][choose][flagX][flagY]) { return dpS[idx][choose][flagX][flagY]; } blS[idx][choose][flagX][flagY] = true; dpS[idx][choose][flagX][flagY] = k + 1; for (int currX = 0 ; currX <= flagX ; ++currX) { for (int currY = flagY ; currY <= 1 ; ++currY) { for (int subtreeChoose = std::max(choose - (1 + (currX == 1)) * pathSizes[idx + 1], currX + currY) ; subtreeChoose <= std::min((currX + currY) * sz[path[idx]], choose) ; ++subtreeChoose) { int val = dpS[idx][choose][flagX][flagY]; dpS[idx][choose][flagX][flagY] = std::min(dpS[idx][choose][flagX][flagY], fStick(idx + 1, choose - subtreeChoose, currX, currY) + std::max((currX == 0 ? 0 : distX[path[idx]]), (currY == 0 ? 0 : distY[path[idx]])) + fRoot(path[idx], subtreeChoose - currX - currY, currX, currY)); } } } return dpS[idx][choose][flagX][flagY]; } int max_score(int N, int X, int Y, long long K, std::vector <int> U, std::vector <int> V, std::vector <int> W) { reset(); n = N; x = X; y = Y; k = K; disjoint = false; for (int i = 0 ; i < n - 1 ; ++i) { g[U[i]].emplace_back(V[i], W[i]); g[V[i]].emplace_back(U[i], W[i]); } dfs(x, -1, distX, 0); dfs(y, -1, distY, 0); if (distX[y] > 2 * k) { disjoint = true; std::vector <llong> vals; for (int i = 0 ; i < n ; ++i) { vals.push_back(distX[i]); vals.push_back(distY[i]); } std::sort(vals.begin(), vals.end()); for (int idx = 0 ; idx < 2 * n ; ++idx) { if (k < vals[idx]) { return idx; } k -= vals[idx]; } assert(false); } dfsPath(x, -1); std::reverse(path.begin(), path.end()); for (const int &i : path) { isOnPath[i] = true; } dfsSize(x, -1); for (int i = 0 ; i < n ; ++i) { suffixSizes[i].resize(g[i].size() + 1, 0); for (int j = g[i].size() - 1 ; j >= 0 ; --j) { int add = 0; suffixSizes[i][j] = suffixSizes[i][j + 1]; if (!isOnPath[g[i][j].first] && g[i][j].first != par[i]) { add = sz[g[i][j].first]; } suffixSizes[i][j] += add; } } pathSizes.resize(path.size() + 1, 0); for (int i = path.size() - 1 ; i >= 0 ; --i) { pathSizes[i] = pathSizes[i + 1] + sz[path[i]]; } for (int i = 2 * n ; i >= 1 ; --i) { if (fStick(0, i, 1, 0) <= k) { return i; } } return 0; }

Compilation message (stderr)

closing.cpp: In function 'llong fChildren(int, int, int, int, int)':
closing.cpp:159:13: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  159 |     if (idx == g[node].size())
      |         ~~~~^~~~~~~~~~~~~~~~~
closing.cpp: In function 'llong fStick(int, int, int, int)':
closing.cpp:195:13: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  195 |     if (idx == path.size())
      |         ~~~~^~~~~~~~~~~~~~
closing.cpp:214:21: warning: unused variable 'val' [-Wunused-variable]
  214 |                 int val = dpS[idx][choose][flagX][flagY];
      |                     ^~~
#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...