CF 741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
2018-09-27 10:22
471 查看
D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
http://codeforces.com/problemset/problem/741/D
题意:
一棵根为1 的树,每条边上有一个字符(a-v共22种)。 求每个子树内的最长的路径,使得路径上的边按照一定顺序排列后是回文串。
分析:
dsu on tree。询问子树信息。
首先将这22个字符,转化为二进制。a=1,b=10,c=100...如果一条路径可以是回文串,那么要求路径的异或和最多有一个1。所以记录下从根到每个点的异或和,那么一条路径的异或和就是dis[u]^dis[v],lca上面的异或后消失了。
之后维护每个子树内异或和为x的最大深度是多少。记为f。
更新答案:按照点分治的思想,先更新不经过根的,然后求出经过根的(更新分成两步,第一步更新答案,第二步更新f数组。防止更新了在子树内部的)。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<iostream> #include<cctype> #include<set> #include<vector> #include<queue> #include<map> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 500005; int head , nxt , to , len , En; int fa , siz , son , dis , deth , ans ; int f[(1 << 22) + 5]; int Mx, D; void add_edge(int u,int v,int w) { ++En; to[En] = v; len[En] = w; nxt[En] = head[u]; head[u] = En; } void dfs(int u) { siz[u] = 1; deth[u] = deth[fa[u]] + 1; for (int i=head[u]; i; i=nxt[i]) { int v = to[i]; fa[v] = u; dis[v] = dis[u] ^ (1 << len[i]); dfs(v); siz[u] += siz[v]; if (!son[u] || siz[son[u]] < siz[v]) son[u] = v; } } void add(int u) { if (f[dis[u]]) Mx = max(Mx, deth[u] + f[dis[u]] - D); // 异或后为0 for (int i=0; i<22; ++i) // 异或后有一个1 if (f[(1 << i) ^ dis[u]]) Mx = max(Mx, deth[u] + f[(1 << i) ^ dis[u]] - D); } void Calc(int u) { // 计算答案 add(u); for (int i=head[u]; i; i=nxt[i]) Calc(to[i]); } void upd(int u) { f[dis[u]] = max(deth[u], f[dis[u]]); } void update(int u) { // 更新f数组 upd(u); for (int i=head[u]; i; i=nxt[i]) update(to[i]); } void Clear(int u) { f[dis[u]] = 0; for (int i=head[u]; i; i=nxt[i]) Clear(to[i]); } void solve(int u,bool c) { for (int i=head[u]; i; i=nxt[i]) if (to[i] != son[u]) solve(to[i], 0); if (son[u]) solve(son[u], 1); D = deth[u] * 2; for (int i=head[u]; i; i=nxt[i]) Mx = max(Mx, ans[to[i]]); //不经过根的 for (int i=head[u]; i; i=nxt[i]) if (to[i] != son[u]) Calc(to[i]), update(to[i]); // update(u) !!! 先更新答案,在更新f数组,(防止计算到在子树内部的路径) add(u); upd(u); ans[u] = Mx; if (!c) Clear(u), Mx = 0; } int main() { int n = read(); char c[10]; for (int i=2; i<=n; ++i) { int u = read(); scanf("%s", c); add_edge(u, i, c[0] - 'a'); } dfs(1); solve(1, 1); for (int i=1; i<=n; ++i) printf("%d ",ans[i]); return 0; }
相关文章推荐
- Codeforces 741D D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 树上启发式合并
- 【CodeForces】741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
- CF 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths [dsu on tree 类似点分治]
- codeforces 741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths (dsu on the tree)
- codeforces741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- [树上启发式合并 && 哈希] Codeforces 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- [Codeforces741D]Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on the tree)
- 【dsu on tree】Codeforces741D[Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths]题解
- Codeforces 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- 【题解】codeforces741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- Codeforces 741.D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- [dsu on tree] Codeforces #741D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths
- codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- CF 742 B-Arpa’s obvious problem and Mehrdad’s terrible solution
- codeforce 741 B. Arpa's weak amphitheater and Mehrdad's valuable Hoses(背包 dp)
- 二分图(Arpa’s overnight party and Mehrdad’s silent entering,cf 741C)
- 【Codeforces 741 B. Arpa's weak amphitheater and Mehrdad's 】+ 并查集 + 01背包
- 思路题,树的直径(Anton and Tree,cf 734E)
- Codeforces 742C C. Arpa's loud Owf and Mehrdad's evil plan
- codeforces 742d D - Arpa's weak amphitheater and Mehrdad's valuable Hoses