CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths相关的知识,希望对你有一定的参考价值。

CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

题意:

一棵根为1 的树,每条边上有一个字符(a-v共22种)。 一条简单路径被称为Dokhtar-kosh当且仅当路径上的字符经过重新排序后可以变成一个回文串。 求每个子树中最长的Dokhtar-kosh路径的长度。

题解:

树上启发式合并的开山之作
树上启发式合并介绍
详细题解
字符重排后为字符串,说明该字符中最多只有一个字符出现奇数次,其余都是偶数次,我们联想到用异或操作
我们将字符都用二进制来表示,比如a是0001,b是0010,以此类推,我们可以根据一条路上的异或和来判断是否为回文串
树上两条路径之间的异或和:
1为根节点
dis(u,v) = dis(u, 1 ) ^ dis(lca(u,v) 1) ^ dis(v,1) ^ dis(lca(u,v) ,1) = dis(u,1) ^ dis(v,1)
所以我们只需要处理出每个点到根节点1的路径异或和Xor(u)=dis(u,1),就可以处理任意两点之间的异或和
当一个路径合法时,当且仅当Xor(u) ^ Xor(v)的二进制数中有且仅有一个1(也就是最多就一个字符为奇数)或者没有1
即合法路径(u,v) 为Xor[u] ^ Xor[v] =0 或者Xor[u] ^ Xor[v] = 2i
我们需要求的就是以 u 为根子树中的两点 x,y,满足 Xor[x] ^ Xor[y] =0 或者Xor[x] ^ Xor[y] = 2i 的点对所有 (x,y)中的最长长度
对于以u为根的子树,树中可能存在最长路径显然有三种:

  1. 不经过根节点u即最长路径在子树里
  2. 路径的一个端点就是跟节点u,即子树中的一点v与u构成路径
  3. 经过u,路径的两端在两个子树中,路径经过u

设f[x]表示当前子树中节点v到根节点u的路径的异或和等于x的结点v的最大深度
对于第一个情况:答案为ans[u]=max(ans[v]),v是u的子节点

对于第二个情况:ans[u]=max( max(f[Xor[u]],f[Xor[u] ^ 2i])-dep[u] ) ,Xor[u] ^ 2i相当于枚举路径的另一个端点

对于第三个情况用到树上启发式合并统计贡献
先算轻儿子,回答询问后,情况轻儿子的贡献,然后处理重儿子,保留重儿子的贡献fi,然后再计算一次剩余的轻儿子,保留贡献在fi中,用于与上层合并。此时经过节点u的路径(x,y)的长度,max(f[ xor[x] ],f[y]) - depth[u] +depth[x]-depth[u], y = xor[x] ^ 2i

代码:

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a);
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define per(i,a,b) for(int i = a; i >= b; i--)
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
typedef long long ll;
typedef double db;
const int inf = 1e8;
const int N = 5e5+10;
const db EPS = 1e-9;
using namespace std;

void dbg() {cout << "\\n";}
template<typename T, typename... A> void dbg(T a, A... x) {cout << a << ' '; dbg(x...);}
#define logs(x...) {cout << #x << " -> "; dbg(x);}

int n,a[N],tot,head[N],sz[N],son[N],f[1<<22],dep[N],ans[N]; //f[i]:表示子树中异或和为f[i]的最大深度
struct Node{
    int to,next;
}e[N];

void add(int x,int y){
    e[++tot].to = y, e[tot].next = head[x], head[x] = tot;
}

void dfs1(int x){
    ans[x] = -inf; sz[x] = 1;
    for(int i = head[x]; i; i = e[i].next){
        int y = e[i].to;
        dep[y] = dep[x]+1; a[y] ^= a[x];
        dfs1(y); sz[x] += sz[y];
        if(sz[y] > sz[son[x]]) son[x] = y;
    }
}

void Delete(int x){
    f[a[x]] = -inf;
    for(int i = head[x]; i; i = e[i].next) Delete(e[i].to);
}

void modify(int x,int fa){
    ans[fa] = max(ans[fa],f[a[x]]+dep[x]-2*dep[fa]);
    
    for(int i = 0; i < 22; i++)
        ans[fa] = max(ans[fa],f[a[x]^(1<<i)]+dep[x]-2*dep[fa]);
        
    for(int i = head[x]; i; i = e[i].next) modify(e[i].to,fa);
}

void ins(int x){
    f[a[x]] = max(f[a[x]],dep[x]);
    for(int i = head[x]; i; i = e[i].next) ins(e[i].to);
}

void dfs2(int x){
    ans[x] = 0;
    for(int i = head[x]; i; i = e[i].next)
        if(e[i].to != son[x]) dfs2(e[i].to), Delete(e[i].to);
    if(son[x]) dfs2(son[x]);
    f[a[x]] = max(f[a[x]],dep[x]);
    //路径经过x
    for(int i = head[x]; i; i = e[i].next) 
        if(e[i].to != son[x]) modify(e[i].to,x), ins(e[i].to);
    //x为路径端点
    ans[x] = max(ans[x],f[a[x]]-dep[x]);
    for(int i = 0; i < 22; i++)
        ans[x] = max(ans[x],f[a[x]^(1<<i)]-dep[x]);
    //路径不经过x
    for(int i = head[x]; i; i = e[i].next) ans[x] = max(ans[x],ans[e[i].to]);
}

int main()
{
    scanf("%d",&n); tot = 1;
    rep(i,0,(1<<22)-1) f[i] = -inf; //不要忘记赋初值
    rep(i,2,n){
        int p; char s[10];
        scanf("%d%s",&p,s);
        add(p,i); a[i] = 1<<(s[0]-'a');
    }
    dfs1(1); dfs2(1);
    rep(i,1,n) printf("%d%c",ans[i]," \\n"[i==n]);
    return 0;
}

以上是关于CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths的主要内容,如果未能解决你的问题,请参考以下文章

「CF741D」Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

(树上启发式合并)CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

CF741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths

CF741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths

codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

cfodeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths