Codeforces Round #383 (Div. 1): D. Arpa’s letter-marked tree…(dsu on tree+狀壓)
阿新 • • 發佈:2018-11-10
題意:
給你一棵n個節點的樹,每條邊都代表著一個字母(a~v),對於每個節點u,求出以u為根的子樹中有多少條路徑滿足:路徑上的字元重新排列後可以得到一個迴文字串
思路:
前置:dsu on tree
然後就可以思考該怎麼O(n²)暴力了
因為只有22個字母,所以可以用一個數字代表當前哪些字母出現了奇數次,如果字典序第i個字母出現奇數次,那麼第i位就為1,否則就為0,這樣的話只要求出val[u]表示從u點到根的路徑狀態,如果val[u]^val[v]==0 或者val[u]^val[v]的二進位制中只有1位是1,那麼路徑u到v就可以重排形成迴文字串
#pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<string> #include<math.h> #include<queue> #include<stack> #include<iostream> using namespace std; #define LL long long #define mod 1000000007 vector<int> G[500005]; int val[4233333], dp[4233333]; int dep[500005], siz[500005], hson[500005], ans[500005]; void Sech1(int u, int p) { int i, v; val[u] ^= val[p]; siz[u] = 1, dep[u] = dep[p]+1; for(i=0;i<G[u].size();i++) { v = G[u][i]; if(v==p) continue; Sech1(v, u); siz[u] += siz[v]; if(siz[v]>siz[hson[u]]) hson[u] = v; } } void Init(int u) { int i, v; dp[val[u]] = -1044266558; for(i=0;i<G[u].size();i++) { v = G[u][i]; Init(v); } } void Update(int u) { int i, v; dp[val[u]] = max(dp[val[u]], dep[u]); for(i=0;i<G[u].size();i++) { v = G[u][i]; Update(v); } } void Gao(int u, int now) { int i, v; ans[now] = max(ans[now], dep[u]+dp[val[u]]); for(i=0;i<=21;i++) ans[now] = max(ans[now], dep[u]+dp[val[u]^(1<<i)]); for(i=0;i<G[u].size();i++) { v = G[u][i]; Gao(v, now); } } void Sech2(int u) { int i, v; for(i=0;i<G[u].size();i++) { v = G[u][i]; if(v==hson[u]) continue; Sech2(v); Init(v); } if(hson[u]) Sech2(hson[u]); for(i=0;i<G[u].size();i++) { v = G[u][i]; if(v==hson[u]) continue; Gao(v, u), Update(v); } dp[val[u]] = max(dp[val[u]], dep[u]); ans[u] = max(ans[u], dep[u]+dp[val[u]]); for(i=0;i<=21;i++) ans[u] = max(ans[u], dep[u]+dp[val[u]^(1<<i)]); ans[u] -= dep[u]*2; for(i=0;i<G[u].size();i++) { v = G[u][i]; ans[u] = max(ans[u], ans[v]); } } int main(void) { char ch; int n, i, x; scanf("%d", &n); for(i=2;i<=n;i++) { scanf("%d %c", &x, &ch); G[x].push_back(i); val[i] = 1<<(ch-'a'); } memset(dp, -62, sizeof(dp)); Sech1(1, 0); Sech2(1); for(i=1;i<=n;i++) printf("%d ", ans[i]); puts(""); return 0; }