【题目】E. Palindromes in a Tree

【题意】给定一棵树,每个点都有一个a~t的字符,一条路径回文定义为路径上的字符存在一个排列构成回文串,求经过每个点的回文路径数。n<=2*10^5。

【算法】点分治

【题解】状压20位的二进制表示一条路径的字符状态,点分治过程中维护扫描过的路径只须维护状态桶数组,t[i]表示前面状态为i的路径条数。

合并:考虑当前状态为j,要使合并的状态满足条件即i^j=1<<k(0<=k<20)或i^j=0,移项得i=j^(1<<k)或i=j,所以路径数是Σ t [ j^(1<<k) ]+t[j]。

统计每个点:对于当前要处理的重心x,先遍历所有子树得到整个t[]数组,然后对每个子树先删除其在桶里的状态,然后扫一遍贡献子树中每个点,最后将子树的状态加回桶中。

这样可以做到每条路径都贡献到每个点,要特殊处理重心的贡献。

复杂度O(n log n)。

#include<cstdio>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=,maxN=;
int tot,first[maxn],sz[maxn],vis[maxn],sum,root,a[maxn],u,v,n;
ll ans[maxn],t[maxN];
struct edge{int v,from;}e[maxn*]; void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
void getroot(int x,int fa){
sz[x]=;
bool ok=;
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v]){
getroot(e[i].v,x);
sz[x]+=sz[e[i].v];
if(sz[e[i].v]>sum/)ok=;
}
if(ok&&sz[x]>=sum/)root=x;
}
void dfs(int x,int fa,int p,int s){
t[s^=(<<a[x])]+=p;
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v])dfs(e[i].v,x,p,s);
}
ll calc(int x,int fa,int s){
s^=(<<a[x]);ll num=t[s];
for(int i=;i<;i++)num+=t[s^(<<i)];
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v])num+=calc(e[i].v,x,s);
ans[x]+=num;
return num;
}
void solve(int x,int s){
vis[x]=;
dfs(x,,,);
ll num=t[];
for(int i=;i<;i++)num+=t[<<i];
for(int i=first[x];i;i=e[i].from)if(!vis[e[i].v]){
dfs(e[i].v,x,-,<<a[x]);
num+=calc(e[i].v,x,);
dfs(e[i].v,x,,<<a[x]);
}
ans[x]+=num/;
dfs(x,,-,);
for(int i=first[x];i;i=e[i].from)if(!vis[e[i].v]){
if(sz[e[i].v]>sz[x])sum=s-sz[x];else sum=sz[e[i].v];
getroot(e[i].v,x);
solve(root,sum);
}
}
char s[maxn];
int main(){
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
insert(u,v);insert(v,u);
}
scanf("%s",s+);
for(int i=;i<=n;i++)a[i]=s[i]-'a';
sum=n;
getroot(,);
solve(root,sum);
for(int i=;i<=n;i++)printf("%lld ",ans[i]+);
return ;
}

【CodeForces】914 E. Palindromes in a Tree 点分治的更多相关文章

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

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

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

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

  3. codeforces 1065F Up and Down the Tree

    题目链接:codeforces 1065F Up and Down the Tree 题意:给出一棵树的节点数\(n\)以及一次移动的最大距离\(k\),现在有一个标记在根节点1处,每一次可以进行一下 ...

  4. Codeforces 914H Ember and Storm's Tree Game 【DP】*

    Codeforces 914H Ember and Storm's Tree Game 题目链接 ORZ佬 果然出了一套自闭题 这题让你算出第一个人有必胜策略的方案数 然后我们就发现必胜的条件就是树上 ...

  5. Codeforces Round #499 (Div. 1) F. Tree

    Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...

  6. CodeForces 1251B --- Binary Palindromes

    [CodeForces 1251B --- Binary Palindromes] Description A palindrome is a string t which reads the sam ...

  7. [Codeforces 553E]Kyoya and Train(期望DP+Floyd+分治FFT)

    [Codeforces 553E]Kyoya and Train(期望DP+Floyd+分治FFT) 题面 给出一个\(n\)个点\(m\)条边的有向图(可能有环),走每条边需要支付一个价格\(c_i ...

  8. codeforces 914E Palindromes in a Tree(点分治)

    You are given a tree (a connected acyclic undirected graph) of n vertices. Vertices are numbered fro ...

  9. Palindromes in a Tree CodeForces - 914E

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

随机推荐

  1. HTML5+规范:Webview的使用详解

    一.知识点 Webview模块管理应用窗口界面,实现多窗口的逻辑控制管理操作.通过plus.webview可获取应用界面管理对象. 1.方法 1.1.all: 获取所有Webview窗口 Array[ ...

  2. lintcode395-硬币排成线 II

    395-硬币排成线 II 有 n 个不同价值的硬币排成一条线.两个参赛者轮流从左边依次拿走 1 或 2 个硬币,直到没有硬币为止.计算两个人分别拿到的硬币总价值,价值高的人获胜. 请判定 第一个玩家 ...

  3. PAT 甲级 1005 Spell It Right

    https://pintia.cn/problem-sets/994805342720868352/problems/994805519074574336 Given a non-negative i ...

  4. 使用selenium遍历frame中的表单信息 ;

    遍历frame中的表单 : package webDriverPro; import java.util.List; import java.util.regex.Matcher; import ja ...

  5. 判断一个变量是不是json,以及如何将变量转换成json

    https://blog.csdn.net/A123638/article/details/52486975这里看到一个很好的方法 // 判断变量是不是jsonisJson(variable: any ...

  6. 10个linux网络和监控命令

    我下面列出来的10个基础的每个linux用户都应该知道的网络和监控命令.网络和监控命令类似于这些: hostname, ping, ifconfig, iwconfig, netstat, nsloo ...

  7. BZOJ 1190 梦幻岛宝珠(分组01背包)

    跑了7000ms... 这是个体积和价值都超大的背包.但是体积保证为a*2^b的(a<=10,b<=30)形式.且n<=100. 于是可以想到按b来分组.这样的话每组最多为a*n*2 ...

  8. 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块

    题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...

  9. 【明哥报错簿】之【解决eclipse项目小红叉】

    解决方案: 0.如果是jdk版本不一致,直接右击项目名称,选择maven里面的update project.原因一般是maven的pom.xml里面设置的编译插件org.apache.maven.pl ...

  10. BZOJ4998 星球联盟(LCT+双连通分量+并查集)

    即要求动态维护边双.出现环时将路径上的点合并即可.LCT维护.具体地,加边成环时makeroot+access+splay一套把这段路径提出来,暴力dfs修改并查集祖先,并将这部分与根断开,视为删除这 ...