You are given a tree (a connected acyclic undirected graph) of n vertices. Vertices are numbered from 1 to n and each vertex is assigned a character from a to t.

A path in the tree is said to be palindromic if at least one permutation of the labels in the path is a palindrome.

For each vertex, output the number of palindromic paths passing through it.

Note: The path from vertex u to vertex v is considered to be the same as the path from vertex v to vertex u, and this path will be counted only once for each of the vertices it passes through.

Input

The first line contains an integer n (2 ≤ n ≤ 2·105)  — the number of vertices in the tree.

The next n - 1 lines each contain two integers u and v (1  ≤  u, v  ≤  n, u ≠ v) denoting an edge connecting vertex u and vertex v. It is guaranteed that the given graph is a tree.

The next line contains a string consisting of n lowercase characters from a to t where the i-th (1 ≤ i ≤ n) character is the label of vertex i in the tree.

Output

Print n integers in a single line, the i-th of which is the number of palindromic paths passing through vertex i in the tree.

Examples
input

Copy
5
1 2
2 3
3 4
3 5
abcbb
output

Copy
1 3 4 3 3 
input

Copy
7
6 2
4 3
3 7
5 2
7 2
1 4
afefdfs
output
1 4 1 1 2 4 2 
Note

In the first sample case, the following paths are palindromic:

2 - 3 - 4

2 - 3 - 5

4 - 3 - 5

Additionally, all paths containing only one vertex are palindromic. Listed below are a few paths in the first sample that are not palindromic:

1 - 2 - 3

1 - 2 - 3 - 4

1 - 2 - 3 - 5

题意:给你一颗 n 个顶点的树(连通无环图)。顶点从 1 到 n 编号,并且每个顶点对应一个在‘a’到‘t’的字母。 树上的一条路径是回文是指至少有一个对应字母的排列为回文。 对于每个顶点,输出通过它的回文路径的数量。 注意:从u到v的路径与从v到u的路径视为相同,只计数一次。

题解:

首先是一个结论
本题要求路径的某个排列为回文串,很显然,路径上最多有一个字母出现奇数次。只需要记录奇偶性显然可以用状压去解决。
根据这个结论,我们可以推出对于一个点u,他到某个点v的路径如果满足条件,显然状压的数字等于0或者1<<i(i<=19),这个时候可以考虑搞出一个中点k,于是问题等价于dis(u,k)^dis(v,k)等于0或者1<<i(i<=19)
这显然是点分治的思路
考虑点分治中的暴力怎么写:首先对于重心进行dfs,求出所有点到重心的dis,dis表示路径上个字母的奇偶性,并且记录 dis_idisi​ 的数量。
接着对于每棵子树将该子树对所有dis的数量贡献全部去掉,再对该子树进行dfs,对于每个点的dis,统计与他异或等于0或者1<<i(i<=19)的数量,即为该点贡献答案,值得注意的是,经过该点的路径一定经过其父节点,因为是从另一颗子树中跑过来的,所以在dfs返回的时候应该给父节点加上子节点的贡献。接着把该子树的dis全部加回去跑下一棵子树。
因为每个点本身都是一个回文串,所以最后答案要加一。

代码如下:

#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define poi void
#define int long long
using namespace std; vector<int> g[];
char c[];
int n,ans[],a[],size[],vis[],f[],tmp[(<<)|]; poi get_size(int now,int fa)
{
size[now]=;
f[now]=fa;
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i]]||g[now][i]==fa) continue;
get_size(g[now][i],now);
size[now]+=size[g[now][i]];
}
} int get_zx(int now,int fa)
{
if(size[now]==) return now;
int son,maxson=-;
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i]]||g[now][i]==fa) continue;
if(maxson<size[g[now][i]])
{
maxson=size[g[now][i]];
son=g[now][i];
}
}
int zx=get_zx(son,now);
while(size[zx]<*(size[now]-size[zx])) zx=f[zx];
return zx;
} poi get(int now,int fa,int sta,int kd)
{
sta^=(<<a[now]);
tmp[sta]+=kd;
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i]]||g[now][i]==fa) continue;
get(g[now][i],now,sta,kd);
}
} int calc(int now,int fa,int sta)
{
sta^=(<<a[now]);
int num=tmp[sta];
for(int i=;i<=;i++)
{
num+=tmp[sta^(<<i)];
}
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i]]||g[now][i]==fa) continue;
num+=calc(g[now][i],now,sta);
}
ans[now]+=num;
return num;
} poi solve(int now)
{
vis[now]=;
get(now,,,);
long long num=tmp[];
for(int i=;i<=;i++)
{
num+=tmp[<<i];
}
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i]]) continue;
get(g[now][i],,<<a[now],-);
num+=calc(g[now][i],,);
get(g[now][i],,<<a[now],);
}
ans[now]+=num/;
get(now,,,-);
for(int i=;i<g[now].size();i++)
{
if(vis[g[now][i]]) continue;
get_size(g[now][i],);
int zx=get_zx(g[now][i],);
solve(zx);
}
} signed main()
{
scanf("%lld",&n);
for(int i=;i<n;i++)
{
int from,to;
scanf("%lld%lld",&from,&to);
g[from].push_back(to);
g[to].push_back(from);
}
scanf("%s",c+);
for(int i=;i<=n;i++)
{
a[i]=c[i]-'a';
}
solve();
for(int i=;i<=n;i++)
{
printf("%lld ",ans[i]+);
}
}

codeforces 914E Palindromes in a Tree(点分治)的更多相关文章

  1. 【CodeForces】914 E. Palindromes in a Tree 点分治

    [题目]E. Palindromes in a Tree [题意]给定一棵树,每个点都有一个a~t的字符,一条路径回文定义为路径上的字符存在一个排列构成回文串,求经过每个点的回文路径数.n<=2 ...

  2. CF914E Palindromes in a Tree(点分治)

    link 题目大意:给定一个n个点的树,每个点都有一个字符(a-t,20个字符) 我们称一个路径是神犇的,当这个路径上所有点的字母的某个排列是回文 求出对于每个点,求出经过他的神犇路径的数量 题解: ...

  3. 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 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...

  4. codeforces 812E Sagheer and Apple Tree(思维、nim博弈)

    codeforces 812E Sagheer and Apple Tree 题意 一棵带点权有根树,保证所有叶子节点到根的距离同奇偶. 每次可以选择一个点,把它的点权删除x,它的某个儿子的点权增加x ...

  5. codeforces 220 C. Game on Tree

    题目链接 codeforces 220 C. Game on Tree 题解 对于 1节点一定要选的 发现对于每个节点,被覆盖切选中其节点的概率为祖先个数分之一,也就是深度分之一 代码 #includ ...

  6. Codeforces E. Alyona and a tree(二分树上差分)

    题目描述: Alyona and a tree time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  7. Palindromes in a Tree CodeForces - 914E

    https://vjudge.net/problem/CodeForces-914E 点分就没一道不卡常的? 卡常记录: 1.把不知道为什么设的(unordered_map)s换成了(int[])s ...

  8. Codeforces 1039D You Are Given a Tree [根号分治,整体二分,贪心]

    洛谷 Codeforces 根号分治真是妙啊. 思路 考虑对于单独的一个\(k\)如何计算答案. 与"赛道修建"非常相似,但那题要求边,这题要求点,所以更加简单. 在每一个点贪心地 ...

  9. Codeforces 434E - Furukawa Nagisa's Tree(三元环+点分治)

    Codeforces 题面传送门 & 洛谷题面传送门 场号 hopping,刚好是我的学号(指 round 的编号) 注:下文中分别用 \(X,Y,K\) 代替题目中的 \(x,y,k\) 注 ...

随机推荐

  1. scp 远程复制

    1. 上传本地文件到远程机器指定目录 命令: scp /opt/soft/nginx-0.5.38.tar.gz root@192.168.120.204:/opt/soft/scptest 上传本地 ...

  2. 分类和逻辑回归(Classification and logistic regression)

    分类问题和线性回归问题问题很像,只是在分类问题中,我们预测的y值包含在一个小的离散数据集里.首先,认识一下二元分类(binary classification),在二元分类中,y的取值只能是0和1.例 ...

  3. 关于No ManagedConnections available within configured blocking timeout异常的解决

    最近由于系统和业务重构需要,需要把线上1亿数据迁移到新库,由于业务变更,新表老表结构有变化,没法直接用dba dump的方式,需要自己写转换程序迁移.今天在调试的时候,碰到一个蛋疼的问题,就是一开始查 ...

  4. Django 组件-cookie 与 session

    会话跟踪技术 1 什么是会话跟踪技术 我们需要先了解一下什么是会话!可以把会话理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应.例如你给10086打个电话,你就是客户端,而10 ...

  5. gridView删除提示框

    实现方法: 双击GridView的OnRowDataBound事件: 在后台的GridView1_RowDataBound()方法添加代码,最后代码如下所示: protected void GridV ...

  6. 奶牛易物-Alpha版本测试报告

    1.在测试过程中总共发现了多少Bug?每个类别的Bug分别为多少个? a. 修复的bug: 1.mapper接口与mapper.xml文件绑定的问题; 2..配置逆向工程的配置文件的问题; 3.在编码 ...

  7. web前端整套面试题(三)--网易的面试题

    题型分析: 一.选择题部分(30分) 元素出栈可能性 排序方法的优缺点 HTTP请求方法 关系型数据库种类 多线程(进程与线程共享) 计算机网络协议 linux指令 JQuery实现方法 二.编程题( ...

  8. 【HDU2138】How many prime numbers

    [题目大意] 给n个数判断有几个素数.(每个数<=2^32) 注意多组数据 [题解] 用Rabin_Miller测试跑得飞快... /************* HDU 2138 by chty ...

  9. 44. Wildcard Matching 有简写的字符串匹配

    [抄题]: Given an input string (s) and a pattern (p), implement wildcard pattern matching with support ...

  10. 764. Largest Plus Sign最大的dfs十字架

    [抄题]: 求挖掉一些区域后,能允许出现的最大十字架 In a 2D grid from (0, 0) to (N-1, N-1), every cell contains a 1, except t ...