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

Just in case somebody missed it: we have wonderful girls in Arpa’s land.

Arpa has a rooted tree (connected acyclic graph) consisting of n vertices. The vertices are numbered 1 through n, the vertex 1 is the root. There is a letter written on each edge of this tree. Mehrdad is a fan of Dokhtar-kosh things. He call a string Dokhtar-kosh, if we can shuffle the characters in string such that it becomes palindrome.

He asks Arpa, for each vertex v, what is the length of the longest simple path in subtree of v that form a Dokhtar-kosh string.

Input
The first line contains integern(1n5105)n (1  ≤  n  ≤  5·10^5) — the number of vertices in the tree.

(n1)(n-  1) lines follow, the i-th of them contain an integer pi+1p_i + 1 and a letter ci+1c_i + 1(1pi+1i,ci+11  ≤  p _i + 1  ≤  i, c _i + 1 is lowercase English letter, between a and v, inclusively), that mean that there is an edge between nodes pi+1p _i + 1 and i+1i + 1 and there is a letter ci+1c _i + 1 written on this edge.

Output
Print n integers. The i-th of them should be the length of the longest simple path in subtree of the i-th vertex that form a Dokhtar-kosh string.

Examples

input
4
1 s
2 a
3 s
output
3 1 1 0 
input
5
1 a
2 h
1 a
4 h
output
4 1 0 1 0 

可構成迴文序列很容易聯想到異或。由於字母只有22種,因此可以用一個二進制數表示某一條邊的字符,如果可構成迴文序列,則路徑上邊值的異或結果爲最多隻有一個1的二進制數。
定義以下變量:
dfn[x]dfn[x]:節點x的時間戳。
mp[x]mp[x]:時間戳爲x的節點序號。
d[x]d[x]:節點x的深度。
mxd[x]mxd[x]:從節點1出發的路徑上的邊異或值爲x,這樣的路徑另一端點的最大深度。
b[x]b[x]:從節點1到節點x的路徑上的邊的異或值。
a[x]a[x]:從節點1到時間戳爲xx的路徑上的邊的異或值。
ans[x]ans[x]:以節點x爲根的子樹中可構成迴文序列的最大路徑長度。
對於以節點x爲根的子樹中,滿足條件最長路徑可能不經過x,因此ans[x]ans[x]可能等於其孩子節點y的ans[y]ans[y]
即:
ans[x]=max(ans[x],ans[y])ans[x]=max(ans[x],ans[y])
滿足條件的最長路徑的起始點可能爲x且其餘點在重兒子中,即:
ans[x]=max(ans[x],mxd[b[x]]d[x],mxd[b[x]xor(2i)]d[x])i[0,21]ans[x] = max(ans[x], mxd[b[x]] - d[x],mxd[b[x] xor(2^i)] - d[x])\quad\forall i\in\mathbb [0,21]
對於滿足條件的最長路徑的起始點爲x且其餘點不在在重兒子中的情況,要更新mxdmxd
mxd[b[x]]=max(mxd[b[x]],d[x])mxd[b[x]]=max(mxd[b[x]],d[x])
這樣後續的計算中會包括這種情況。
滿足條件的最長路徑可能經過x,端點在x的兩棵不同的子樹中。這裏需要利用樹上啓發式合併,mxdmxd保存的是重兒子各狀態的最大深度,枚舉輕兒子中的節點,更新ansans

ans[x]=max(ans[x],d[y]+mxd[b[y]]2×d[x],d[y]+mxd[b[y]xor(2i)]2×d[x])i[0,21]yxans[x]=max(ans[x],d[y] + mxd[b[y]] - 2 × d[x],d[y] + mxd[b[y] xor(2^i)] - 2 × d[x])\\\quad\forall i\in\mathbb [0,21] \quad\forall y\in\mathbb x的某棵子樹上的節點
在計算完一棵輕兒子的同時不要忘了更新mxdmxd
mxd[b[x]]=max(mxd[b[x]],d[x])mxd[b[x]] = max(mxd[b[x]], d[x])

#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 5e5 + 10, M = 45e5;
int head[N], ver[N << 1], Next[N << 1], edge[N << 1], tot;
int n, son[N], d[N], mxd[M], s[N], dfn[N], a[N], b[N], num, ans[N], mp[N];

inline void add(int x, int y, int z) {
    ver[++tot] = y;
    Next[tot] = head[x];
    edge[tot] = z;
    head[x] = tot;
}

inline void read() {
    n = qr();
    repi(y, 2, n) {
        int x = qr();
        char z = getchar();
        add(x, y, 1 << (z - 'a'));
        add(y, x, 1 << (z - 'a'));
    }
}

void dfs(int x, int f) {
    dfn[x] = ++num, mp[num] = x, s[x] = 1;
    reps(x) {
        int y = ver[i], z = edge[i];
        if (y == f)continue;
        d[y] = d[x] + 1, b[y] = b[x] ^ z;
        dfs(y, x), s[x] += s[y];
        son[x] = s[y] > s[son[x]] ? y : son[x];
    }
}

void dfs(int x, int f, bool k) {
    reps(x) {
        int y = ver[i];
        if (y != f && y != son[x])
            dfs(y, x, false), ans[x] = max(ans[x], ans[y]);
    }
    if (son[x])dfs(son[x], x, true), ans[x] = max(ans[x], ans[son[x]]);
    ans[x] = max(ans[x], mxd[b[x]] - d[x]);
    repi(i, 0, 21)ans[x] = max(ans[x], mxd[b[x] ^ (1 << i)] - d[x]);
    mxd[b[x]] = max(mxd[b[x]], d[x]);
    reps(x) {
        int y = ver[i];
        if (y == f || y == son[x])continue;
        repi(j, dfn[y], dfn[y] + s[y] - 1) {
            if (mxd[a[j]])ans[x] = max(ans[x], d[mp[j]] + mxd[a[j]] - 2 * d[x]);
            repi(l, 0, 21)if (mxd[a[j] ^ (1 << l)])
                    ans[x] = max(ans[x], d[mp[j]] + mxd[a[j] ^ (1 << l)] - 2 * d[x]);
        }
        repi(j, dfn[y], dfn[y] + s[y] - 1)mxd[a[j]] = max(mxd[a[j]], d[mp[j]]);
    }
    if (!k)repi(i, dfn[x], dfn[x] + s[x] - 1)mxd[a[i]] = 0;
}

int main() {
    read();
    dfs(1, 0);
    repi(i, 1, n)a[dfn[i]] = b[i];
    dfs(1, 0, true);
    repi(i, 1, n)printf("%d%c", ans[i], ce(i, n));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章