# |
Submission time |
Handle |
Problem |
Language |
Result |
Execution time |
Memory |
920902 |
2024-02-03T07:31:41 Z |
Gr47 |
Factories (JOI14_factories) |
C++17 |
|
8000 ms |
261360 KB |
#include "factories.h"
#include <bits/stdc++.h>
using namespace std;
class CentroidDecomposition
{
private:
int n;
vector<bool> vis;
vector<int> sz;
const vector<vector<int>> &tree;
int find_size(int v, int p = -1)
{
if (vis[v])
return 0;
sz[v] = 1;
for (const int &x : tree[v])
if (x != p)
sz[v] += find_size(x, v);
return sz[v];
}
int find_centroid(int v, int p, int cur_sz)
{
for (const int &x : tree[v])
if (x != p)
if (!vis[x] && sz[x] > (cur_sz / 2))
return find_centroid(x, v, cur_sz);
return v;
}
void init_centroid(int v, int p)
{
find_size(v);
int c = find_centroid(v, -1, sz[v]);
vis[c] = true;
centroid_par[c] = p;
if (p == -1)
root = c;
else
centorid_tree[p].push_back(c);
for (const int &x : tree[c])
if (!vis[x])
init_centroid(x, c);
}
public:
vector<vector<int>> centorid_tree;
vector<int> centroid_par;
int root;
CentroidDecomposition(vector<vector<int>> &_tree) : tree(_tree)
{
root = 0;
n = tree.size();
centorid_tree.resize(n);
vis.resize(n, false);
sz.resize(n, 0);
centroid_par.resize(n, -1);
init_centroid(0, -1);
}
};
struct LCA
{
int N;
static const int D = 20;
vector<vector<int>> table;
vector<vector<long long>> seg;
vector<int> depth;
LCA(vector<vector<int>> &tree, map<pair<int, int>, long long> &edge)
{
N = tree.size();
depth.assign(N, 0);
table.assign(D, vector<int>(N, -1));
seg.assign(D, vector<long long>(N, 0LL));
dfs(0, -1, tree, edge);
for (int i = 1; i < D; i++)
{
for (int u = 0; u < N; u++)
{
if (table[i - 1][u] >= 0)
{
table[i][u] = table[i - 1][table[i - 1][u]];
seg[i][u] = seg[i - 1][table[i - 1][u]] + seg[i - 1][u];
}
else
table[i][u] = -1;
}
}
}
void dfs(int u, int p, vector<vector<int>> &tree, map<pair<int, int>, long long> &edge)
{
table[0][u] = p;
if (p != -1)
seg[0][u] = edge[make_pair(u, p)];
for (int v : tree[u])
{
if (v == p)
continue;
depth[v] = depth[u] + 1;
dfs(v, u, tree, edge);
}
}
int up(int u, int dist)
{
for (int i = D - 1; i >= 0; i--)
{
if ((dist & (1 << i)) > 0)
{
u = table[i][u];
if (u == -1)
return -1;
}
}
return u;
}
int lca(int u, int v)
{
if (depth[u] < depth[v])
{
return lca(v, u);
}
int diff = depth[u] - depth[v];
u = up(u, diff);
if (u == v)
return u;
for (int i = D - 1; i >= 0; i--)
{
if (table[i][u] != table[i][v])
{
u = table[i][u];
v = table[i][v];
}
}
return table[0][u];
}
int distance(int u, int v)
{
int w = lca(u, v);
return depth[u] + depth[v] - 2 * depth[w];
}
// get combined segment for [u(0),u(1),u(2),....u(up_walk)] where u(i+1) is parent of u(i) and u(0) = u
long long combined_segment(int u, int up_walk)
{
long long res = 0;
for (int i = D - 1; i >= 0; i--)
{
if ((up_walk & (1 << i)) > 0)
{
res += seg[i][u];
u = table[i][u];
}
}
return res;
}
long long path_segment(int u, int v)
{
int lc = lca(u, v);
return combined_segment(u, depth[u] - depth[lc]) + combined_segment(v, depth[v] - depth[lc]);
}
};
LCA *lca;
CentroidDecomposition *cd;
vector<long long> best;
const long long inf = 1e18;
void Init(int N, int A[], int B[], int D[])
{
map<pair<int, int>, long long> edge;
vector<vector<int>> tree(N);
for (int i = 0; i < N - 1; i++)
{
tree[A[i]].push_back(B[i]);
tree[B[i]].push_back(A[i]);
edge[make_pair(A[i], B[i])] = D[i];
edge[make_pair(B[i], A[i])] = D[i];
}
lca = new LCA(tree, edge);
cd = new CentroidDecomposition(tree);
best.resize(N, inf);
}
void add_node(int u)
{
best[u] = 0;
int p = u;
while (p != cd->root)
{
p = cd->centroid_par[p];
best[p] = min(best[p], lca->path_segment(u, p));
}
}
void rem_node(int u)
{
best[u] = inf;
int p = u;
while (p != cd->root)
{
p = cd->centroid_par[p];
if (best[p] == inf)
break;
best[p] = inf;
}
}
long long get_min_dist(int u)
{
long long ans = inf;
int cur = u;
while (cur != -1)
{
ans = min(ans, best[cur] + lca->path_segment(u, cur));
cur = cd->centroid_par[cur];
}
return ans;
}
long long Query(int S, int X[], int T, int Y[])
{
long long ans = inf;
for (int i = 0; i < S; i++)
add_node(X[i]);
for (int i = 0; i < T; i++)
ans = min(ans, get_min_dist(Y[i]));
for (int i = 0; i < S; i++)
rem_node(X[i]);
return ans;
}
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
22 ms |
17240 KB |
Output is correct |
2 |
Correct |
985 ms |
28244 KB |
Output is correct |
3 |
Correct |
2071 ms |
28348 KB |
Output is correct |
4 |
Correct |
2120 ms |
28332 KB |
Output is correct |
5 |
Correct |
2629 ms |
28684 KB |
Output is correct |
6 |
Correct |
321 ms |
28196 KB |
Output is correct |
7 |
Correct |
2080 ms |
28496 KB |
Output is correct |
8 |
Correct |
2195 ms |
28224 KB |
Output is correct |
9 |
Correct |
2549 ms |
28752 KB |
Output is correct |
10 |
Correct |
289 ms |
28192 KB |
Output is correct |
11 |
Correct |
2045 ms |
28504 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
5 ms |
16988 KB |
Output is correct |
2 |
Correct |
6917 ms |
255860 KB |
Output is correct |
3 |
Execution timed out |
8099 ms |
261360 KB |
Time limit exceeded |
4 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
22 ms |
17240 KB |
Output is correct |
2 |
Correct |
985 ms |
28244 KB |
Output is correct |
3 |
Correct |
2071 ms |
28348 KB |
Output is correct |
4 |
Correct |
2120 ms |
28332 KB |
Output is correct |
5 |
Correct |
2629 ms |
28684 KB |
Output is correct |
6 |
Correct |
321 ms |
28196 KB |
Output is correct |
7 |
Correct |
2080 ms |
28496 KB |
Output is correct |
8 |
Correct |
2195 ms |
28224 KB |
Output is correct |
9 |
Correct |
2549 ms |
28752 KB |
Output is correct |
10 |
Correct |
289 ms |
28192 KB |
Output is correct |
11 |
Correct |
2045 ms |
28504 KB |
Output is correct |
12 |
Correct |
5 ms |
16988 KB |
Output is correct |
13 |
Correct |
6917 ms |
255860 KB |
Output is correct |
14 |
Execution timed out |
8099 ms |
261360 KB |
Time limit exceeded |
15 |
Halted |
0 ms |
0 KB |
- |