제출 #1167314

#제출 시각아이디문제언어결과실행 시간메모리
1167314turnejaLampice (COCI19_lampice)C++20
17 / 110
3447 ms20352 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> using namespace std; using namespace __gnu_pbds; #define endl "\n" #define ll long long #define IOS ios_base::sync_with_stdio(false); cin.tie(nullptr); const int N = 1e5 + 5; const int K = 19; const long long M = 1e9 + 7; const long long P = 26, INV_P = 576923081; const long long Q = 9923, INV_Q = 452282579; struct chash { long long operator()(pair<long long, long long> x) const { return x.first* M + x.second; } }; pair<long long, long long> single(char a) { return make_pair(a - 'a' + 1, a - 'a' + 1); } pair<long long, long long> mul(pair<long long, long long> a, pair<long long, long long> b) { return make_pair(a.first * b.first % M, a.second * b.second % M); } pair<long long, long long> sub(pair<long long, long long> a, pair<long long, long long> b) { return make_pair((a.first - b.first + M) % M, (a.second - b.second + M) % M); } pair<long long, long long> add(pair<long long, long long> a, pair<long long, long long> b) { return make_pair((a.first + b.first + M) % M, (a.second + b.second + M) % M); } string s; int sz[N]; bool seen_c[N]; int parent_c[N]; int depth[N]; int color[N]; int up[K][N]; long long pw_p[N], pw_q[N]; long long inv_p[N], inv_q[N]; vector<int> adj[N]; pair<long long, long long> rising[N], falling[N]; gp_hash_table<pair<long long, long long>, int, chash> mp; int ans = 1; bool found = false; int kth(int v, int k) { while (k > 0) { int l = log2(k); v = up[l][v]; k ^= 1 << l; } return v; } void dfs_subtree(int u, int p) { sz[u] = 1; for (int v : adj[u]) { if (v != p && !seen_c[v]) { dfs_subtree(v, u); sz[u] += sz[v]; } } return; } int dfs_centroid(int u, int p, int n) { for (int v : adj[u]) { if (v != p && !seen_c[v] && sz[v] > n / 2) { return dfs_centroid(v, u, n); } } return u; } void dfs1(int u, int p) { up[0][u] = p; for (int i = 1; i < K; i++) { up[i][u] = up[i - 1][up[i - 1][u]]; } rising[u] = add(rising[p], mul(single(s[u]), make_pair(pw_p[depth[u]], pw_q[depth[u]]))); falling[u] = add(mul(falling[p], make_pair(P, Q)), single(s[u])); for (int v : adj[u]) { if (v != p && !seen_c[v]) { depth[v] = depth[u] + 1; dfs1(v, u); } } return; } void dfs2(int u, int p, int k) { if (depth[u] + 1 == k) { if (rising[u] == falling[u]) { found = true; } } else if (depth[u] + 1 < k) { int anc = k - (depth[u] + 1); if (anc <= depth[u]) { anc = kth(u, anc); if (rising[anc] == falling[anc]) { pair<long long, long long> h = mul(sub(rising[u], rising[anc]), make_pair(inv_p[depth[anc] + 1], inv_q[depth[anc] + 1])); auto it = mp.find(h); if (it != mp.end()) { found = true; } } } } for (int v : adj[u]) { if (v != p && !seen_c[v]) { dfs2(v, u, k); } } return; } void dfs3(int u, int p, int c) { mp[mul(sub(rising[u], rising[c]), make_pair(INV_P, INV_Q))] = 1; for (int v : adj[u]) { if (v != p && !seen_c[v]) { dfs3(v, u, c); } } return; } void build(int u, int p, int n) { dfs_subtree(u, u); int c = dfs_centroid(u, u, sz[u]); if (p == -1) { p = c; } parent_c[c] = p; seen_c[c] = true; rising[c] = make_pair(s[c] - 'a' + 1, s[c] - 'a' + 1); falling[c] = rising[c]; up[0][c] = c; for (int i = 1; i < K; i++) { up[i][c] = c; } depth[c] = 0; for (int v : adj[c]) { if (!seen_c[v]) { depth[v] = 1; dfs1(v, c); } } int l = 0, r = n; while (l <= r) { found = false; int mid = (l + r) / 2; for (int v : adj[c]) { if (!seen_c[v]) { dfs2(v, c, 2 * mid + 1); dfs3(v, c, c); } } mp.clear(); reverse(adj[c].begin(), adj[c].end()); for (int v : adj[c]) { if (!seen_c[v]) { dfs2(v, c, 2 * mid + 1); dfs3(v, c, c); } } mp.clear(); reverse(adj[c].begin(), adj[c].end()); if (found) { ans = max(ans, 2 * mid + 1); l = mid + 1; } else { r = mid - 1; } } l = 1, r = n; while (l <= r) { found = false; int mid = (l + r) / 2; for (int v : adj[c]) { if (!seen_c[v]) { dfs2(v, c, 2 * mid); dfs3(v, c, c); } } mp.clear(); reverse(adj[c].begin(), adj[c].end()); for (int v : adj[c]) { if (!seen_c[v]) { dfs2(v, c, 2 * mid); dfs3(v, c, c); } } mp.clear(); reverse(adj[c].begin(), adj[c].end()); if (found) { ans = max(ans, 2 * mid); l = mid + 1; } else { r = mid - 1; } } for (int v : adj[c]) { if (!seen_c[v]) { build(v, c, n); } } return; } int main() { IOS; int n; cin >> n >> s; pw_p[0] = 1, pw_q[0] = 1; inv_p[0] = 1, inv_q[0] = 1; for (int i = 1; i < n; i++) { pw_p[i] = pw_p[i - 1] * P % M; pw_q[i] = pw_q[i - 1] * Q % M; inv_p[i] = inv_p[i - 1] * INV_P % M; inv_q[i] = inv_q[i - 1] * INV_Q % M; } for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; u--, v--; adj[u].push_back(v); adj[v].push_back(u); } build(0, -1, n); cout << ans; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...