#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7; // pe constante e mai rapid??
struct custom_hash
{
static uint64_t splitmix64(uint64_t x)
{
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const
{
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
int random(int st, int dr)
{
uniform_int_distribution<mt19937::result_type> gen(st, dr);
return gen(rng);
}
struct lampice
{
int n;
vector<vector<int>> g;
vector<char> colors;
vector<bool> seen;
vector<int> sz;
vector<int> depth;
vector<int> hashup;
vector<int> hashdown;
vector<vector<int>> rmq;
const int bsize = 15;
void init(int _n)
{
n = _n;
g = vector<vector<int>>(n + 1);
colors = vector<char>(n + 1);
seen = vector<bool>(n + 1);
sz = depth = hashup = hashdown = vector<int>(n + 1);
rmq = vector<vector<int>>(n + 1, vector<int>(bsize + 1));
}
void set_color(int pos, char x)
{
colors[pos] = x;
}
void add_edge(int a, int b)
{
g[a].push_back(b);
g[b].push_back(a);
}
void dfs_size(int node, int parent)
{
sz[node] = 1;
for (auto i : g[node])
{
if (i != parent && !seen[i])
{
dfs_size(i, node);
sz[node] += sz[i];
}
}
}
int find_centroid(int node, int parent, int size)
{
for (auto i : g[node])
{
if (i != parent && !seen[i] && sz[i] > size / 2)
{
return find_centroid(i, node, size);
}
}
return node;
}
bool solve(int node, int k)
{
int base = random(2, 2);
int max_depth = 0;
function<void(int, int, int)> dfs_init = [&](int node, int parent, int d)
{
rmq[node][0] = parent;
for (int i = 1; i <= bsize; ++i)
{
rmq[node][i] = rmq[rmq[node][i - 1]][i - 1];
}
depth[node] = d;
max_depth = max(max_depth, d);
for (auto i : g[node])
{
if (i != parent && !seen[i])
{
dfs_init(i, node, d + 1);
}
}
};
dfs_init(node, 0, 0);
vector<int> power(max_depth + 1);
power[0] = 1;
for (int i = 1; i <= max_depth; ++i)
{
power[i] = (1ll * power[i - 1] * base) % mod;
}
function<void(int, int)> compute_hash = [&](int node, int parent)
{
hashup[node] = ((1ll * base * hashup[parent]) % mod + (colors[node] - 'a' + 1)) % mod;
hashdown[node] = (hashdown[parent] + (1ll * power[depth[node]] * (colors[node] - 'a' + 1)) % mod) % mod;
for (auto i : g[node])
{
if (i != parent && !seen[i])
{
compute_hash(i, node);
}
}
};
compute_hash(node, 0);
function<int(int, int)> get_hashup = [&](int a, int b)
{
int c = rmq[b][0];
return (hashup[a] - (1ll * hashup[c] * power[depth[a] - depth[c]]) % mod + mod) % mod;
};
function<int(int, int)> kth = [&](int node, int k)
{
int ans = node;
for (int i = bsize; i >= 0; --i)
{
if (k & (1 << i))
{
ans = rmq[ans][i];
}
}
return ans;
};
unordered_set<int, custom_hash> exista;
function<void(int, int, int)> add_subtree = [&](int node, int parent, int root)
{
exista.insert(get_hashup(node, root));
for (auto i : g[node])
{
if (i != parent && !seen[i])
{
add_subtree(i, node, root);
}
}
};
bool este = false;
function<void(int, int, int)> dfs = [&](int node, int parent, int d)
{
if (este)
{
return;
}
for (auto i : g[node])
{
if (i != parent && !seen[i])
{
dfs(i, node, d + 1);
}
}
int t = 2 * d - k;
int l = k - d;
if (t < 0 || l < 0)
{
return;
}
if (l == 0)
{
if (hashup[node] == hashdown[node])
{
este = true;
}
}
else
{
int qui = kth(node, l);
if (hashup[qui] == hashdown[qui] && exista.find(get_hashup(node, kth(node, l - 1))) != exista.end())
{
este = true;
}
}
};
for (auto i : g[node])
{
if (!seen[i])
{
dfs(i, node, 2);
if (este)
{
return este;
}
add_subtree(i, node, i);
}
}
return false;
}
bool decomp(int node, int k)
{
if (k > n)
{
return false;
}
dfs_size(node, 0);
node = find_centroid(node, 0, sz[node]);
if (solve(node, k))
{
return true;
}
reverse(g[node].begin(), g[node].end());
if (solve(node, k))
{
return true;
}
reverse(g[node].begin(), g[node].end());
seen[node] = true;
for (auto i : g[node])
{
if (!seen[i])
{
if (decomp(i, k))
{
return true;
}
}
}
return false;
}
void reinit()
{
seen = vector<bool>(n + 1);
}
};
int32_t main()
{
cin.tie(nullptr)->sync_with_stdio(false);
int n;
cin >> n;
lampice g;
g.init(n);
for (int i = 1; i <= n; ++i)
{
char x;
cin >> x;
g.set_color(i, x);
}
for (int i = 1; i < n; ++i)
{
int u, v;
cin >> u >> v;
g.add_edge(u, v);
}
int ans = 1;
int st = 1, dr = n;
while (st <= dr)
{
int mid = (st + dr) / 2;
if (g.decomp(1, 2 * mid))
{
ans = max(ans, 2 * mid);
st = mid + 1;
}
else
{
dr = mid - 1;
}
g.reinit();
}
st = 1, dr = n;
while (st <= dr)
{
int mid = (st + dr) / 2;
if (g.decomp(1, 2 * mid + 1))
{
ans = max(ans, 2 * mid + 1);
st = mid + 1;
}
else
{
dr = mid - 1;
}
g.reinit();
}
cout << ans;
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
8 ms |
340 KB |
Output is correct |
2 |
Correct |
25 ms |
468 KB |
Output is correct |
3 |
Correct |
100 ms |
648 KB |
Output is correct |
4 |
Correct |
140 ms |
748 KB |
Output is correct |
5 |
Correct |
0 ms |
212 KB |
Output is correct |
6 |
Correct |
0 ms |
212 KB |
Output is correct |
7 |
Correct |
0 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Execution timed out |
5030 ms |
13300 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Execution timed out |
5053 ms |
12452 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
8 ms |
340 KB |
Output is correct |
2 |
Correct |
25 ms |
468 KB |
Output is correct |
3 |
Correct |
100 ms |
648 KB |
Output is correct |
4 |
Correct |
140 ms |
748 KB |
Output is correct |
5 |
Correct |
0 ms |
212 KB |
Output is correct |
6 |
Correct |
0 ms |
212 KB |
Output is correct |
7 |
Correct |
0 ms |
212 KB |
Output is correct |
8 |
Execution timed out |
5030 ms |
13300 KB |
Time limit exceeded |
9 |
Halted |
0 ms |
0 KB |
- |