【题目】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=200010,maxN=2000010;
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*2];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]=1;bool ok=1;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/2)ok=0;}if(ok&&sz[x]>=sum/2)root=x;
}
void dfs(int x,int fa,int p,int s){t[s^=(1<<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^=(1<<a[x]);ll num=t[s];for(int i=0;i<20;i++)num+=t[s^(1<<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]=1;dfs(x,0,1,0);ll num=t[0];for(int i=0;i<20;i++)num+=t[1<<i];for(int i=first[x];i;i=e[i].from)if(!vis[e[i].v]){dfs(e[i].v,x,-1,1<<a[x]);num+=calc(e[i].v,x,0);dfs(e[i].v,x,1,1<<a[x]);}ans[x]+=num/2;dfs(x,0,-1,0);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=1;i<n;i++){scanf("%d%d",&u,&v);insert(u,v);insert(v,u);}scanf("%s",s+1);for(int i=1;i<=n;i++)a[i]=s[i]-'a';sum=n;getroot(1,0);solve(root,sum);for(int i=1;i<=n;i++)printf("%lld ",ans[i]+1);return 0;
}

View Code

转载于:https://www.cnblogs.com/onioncyc/p/8334111.html

【CodeForces】914 E. Palindromes in a Tree 点分治相关推荐

  1. Codeforces Round #507 (Div. 1) D. You Are Given a Tree 根号分治 + dp

    传送门 题意: 有一颗nnn个节点的树,其中一个简单路径集合被称为kkk合法当且仅当: 树的每个节点至多属于一条路径,且每条路径恰好包含kkk个点. 对于k∈[1,n]k\in [1,n]k∈[1,n ...

  2. Codeforces 600E. Lomsat gelral(Dsu on tree学习)

    题目链接:http://codeforces.com/problemset/problem/600/E n个点的有根树,以1为根,每个点有一种颜色.我们称一种颜色占领了一个子树当且仅当没有其他颜色在这 ...

  3. Codeforces Round #316 (Div. 2) D. Tree Requests dfs序

    题目链接: 题目 D. Tree Requests time limit per test:2 seconds memory limit per test:256 megabytes 问题描述 Rom ...

  4. Codeforces 741 D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    D - Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位 ...

  5. 【CodeForces - 1153D】Serval and Rooted Tree(树形dp)

    题干: Now Serval is a junior high school student in Japari Middle School, and he is still thrilled on ...

  6. 【CodeForces - 260D】Black and White Tree (思维构造,猜结论,细节,构造一棵树)

    题干: The board has got a painted tree graph, consisting of n nodes. Let us remind you that a non-dire ...

  7. ☆【CodeForces - 764C】Timofey and a tree (思维题,树的性质)

    题干: Each New Year Timofey and his friends cut down a tree of n vertices and bring it home. After tha ...

  8. Codeforces Round #646 (Div. 2)E. Tree Shuffling 题解(dfs)

    题目链接 题目大意 给你一颗树,每一个节点有一个a[i],b[i],c[i]值,你要把b[i]变成c[i],b[i]和c[i]为[0,1],你操作的方法是,选择一个节点x,选择他的k个子树,然后进行交 ...

  9. Codeforces Round #506 (Div. 3) - E. Tree with Small Distances

    题目链接 题意 给你一棵树,最多加几条边,使点1到所有的点的最大距离不超过2 AC 贪心 从距离最远的点开始,找到他的父节点,然后把父节点相连的点删去,这样最好的情况可以删除三层点 遍历树的时候有两种 ...

最新文章

  1. React Native升级目标SDK
  2. 内网linux服务器安装运行环境,linux下如何在内网中安装docker_网站服务器运行维护...
  3. SVM实战:如何进行乳腺癌检测
  4. User Mode Driver Management介绍(一)
  5. drools。drools_Drools Planner重命名为OptaPlanner:宣布www.optaplanner.org
  6. 一个漂亮而强大的RecyclerView
  7. 907计算机专业基础与408相比,2018年北京大学信息科学技术学院907计算机专业基础之计算机操作系统考研强化五套模拟题...
  8. 【笔记】《离散数学》第十章 递推方程与生成函数
  9. Android检测wifi信号强度,检测网络是否通畅
  10. Mac电脑怎样网络在线重装系统
  11. emule服务器有响应,eMule刚连上服务器就断请教为什么
  12. L6470H_电机驱动控制器 L6470HTR_中文规格书
  13. 第二章 核心动画渲染框架
  14. 已解决:win11无法连接网络共享打印机的方法
  15. 7-114 用if-else语句编程百分制成绩转换为五分制成绩
  16. fiddler对浏览器、app抓包及证书安装
  17. 手机黑名单,拦截电话和短信,清除通话记录
  18. Maven 手工上传JAR包到私有仓库
  19. Java set 和 map 学习记录
  20. xshell 链接linux桌面,Xshell远程桌面连接Linux系统的操作步骤

热门文章

  1. 如何用mysql运行程序_如何在MySQL工作台中创建和执行程序
  2. mysql大量数据分页优化_mysql大量数据分页优化
  3. tensorflow学习(3.tensorboard的使用)
  4. 【知识星球】重要小结与涨价预告
  5. 全球及中国高强度钢行业发展态势与市场规模分析报告2022版
  6. 中国电容器行业产能趋势与投资竞争力研究报告2022版
  7. 开发ASP.NET Atlas服务器端Extender控件——基本概念以及预先需求
  8. 微信公众平台操作获取token类
  9. Git中.gitignore文件的使用
  10. C++模板类注意事项