Codeforces 714D [树上启发式合并][Hash]
2017-08-27 20:58
381 查看
Description
给定一颗字典树。对于每个节点的子树求一条最长的链,其中的边权的字母组成的串经过一定排序后是回文串。Solution
首先合法的链中的字母个数要不都是偶数,要不只有一个奇数。就想到哈希的思想,然后启发式合并。gjghfd大神教我树上启发式合并!!!
将树长链剖分,每次重儿子的信息保留,轻儿子暴力dfs。
这个题有一个小trick,可以预处理一个f数组,fu表示根到节点u的哈希值。那么链(u,v)合法,就等价于bitcount(fu xor fv)≤1。
启发式合并的过程中维护一个dis数组,disfu表示当前处理过的所有子树中fu的值最深的深度。
每次都先递归轻儿子,再递归重儿子,再枚举轻儿子的子树,先更新ans,再更新dis。
有一些小细节。
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; inline char get(void) { static char buf[100000], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, 100000, stdin); if (S == T) return EOF; } return *S++; } inline void read(int &x) { static char c; x = 0; for (c = get(); c < '0' || c > '9'; c = get()); for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0'; } const int N = 501010; const int INF = 1 << 30; int dfc, n, x, Gcnt; char c; struct edge { int to, next; edge(int t = 0, int n = 0):to(t), next(n) {} }; edge G[N << 1]; int head , ans ; int f , dis[1 << 23]; int pre , post , id ; int son , size , dep ; int bin[23]; inline int Max(int a, int b) { return a > b ? a : b; } inline void AddEdge(int from, int to) { G[++Gcnt] = edge(to, head[from]); head[from] = Gcnt; } void dfs1(int u) { pre[u] = ++dfc; size[u] = 1; int to; id[dfc] = u; for (int i = head[u]; i; i = G[i].next) { to = G[i].to; dep[to] = dep[u] + 1; dfs1(to); size[u] += size[to]; if (size[son[u]] < size[to]) son[u] = to; } post[u] = dfc; } inline int mxdep(int S) { int mx = -INF; if (dis[S]) mx = dis[S]; for (int i = 0; i < 22; i++) if (dis[S ^ bin[i]]) mx = Max(mx, dis[S ^ bin[i]]); return mx; } void dfs(int u, int iw) { for (int i = head[u]; i; i = G[i].next) if (G[i].to != son[u]) dfs(G[i].to, 1); if (son[u]) dfs(son[u], 0); for (int i = head[u]; i; i = G[i].next) { int to = G[i].to; ans[u] = Max(ans[u], ans[to]); if (to != son[u]) { for (int j = pre[to]; j <= post[to]; j++) ans[u] = Max(ans[u], mxdep(f[id[j]]) + dep[id[j]] - dep[u] * 2); for (int j = pre[to]; j <= post[to]; j++) dis[f[id[j]]] = Max(dis[f[id[j]]], dep[id[j]]); } } dis[f[u]] = Max(dis[f[u]], dep[u]); ans[u] = Max(ans[u], mxdep(f[u]) - dep[u]); if (iw) for (int i = pre[u]; i <= post[u]; i++) dis[f[id[i]]] = 0; } int main(void) { read(n); for (int i = 0; i < 22; i++) bin[i] = 1 << i; for (int i = 2; i <= n; i++) { read(x); c = get(); f[i] = f[x] ^ bin[c - 'a']; AddEdge(x, i); } dfs1(1); dfs(1, 0); for (int i = 1; i <= n; i++) printf("%d ", ans[i]); putchar('\n'); return 0; }
相关文章推荐
- dsu on tree(树上启发式合并)简介(codeforces 600 E)
- [树上启发式合并 && 哈希] Codeforces 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- Codeforces 741D D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 树上启发式合并
- Codeforces 600E. Lomsat gelral(树上启发式合并)
- Codeforces 600E Lomsat gelral [dsu on tree(树上启发式合并)]
- Codeforces 600E Lomsat gelral 树上启发式合并
- codeforces 375D . Tree and Queries 启发式合并 || dfs序+莫队
- [BZOJ4919][Lydsy六月份月赛 .C][树上DP][启发式合并]大根堆
- 树上启发式合并 DSU On Tree
- BZOJ 3123: [Sdoi2013]森林 启发式合并 树上主席树
- 树上启发式合并
- Codeforces 600 E. Lomsat gelral (dfs启发式合并map)
- [ 网络流 树上启发式合并 主席树 ] BZOJ3681
- codeforces 600E. Lomsat gelral 启发式合并
- CodeForces 827D Best Edge Weight (倍增 启发式合并 链剖 并查集)
- Codeforces 600E Lomsat gelral(启发式合并)
- [BZOJ2599][IOI2011]Race-树上启发式合并(dsu on tree)
- [bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+倍增lca+启发式合并)
- CodeForces 932F Escape Through Leaf [set启发式合并+维护凸包+二分]
- [后缀自动机][树上启发式合并] LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度