codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
题目链接:Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
第一次写\(dsu\ on\ tree\),来记录一下
\(dsu\ on\ tree\)主要维护子树信息,往往可以省掉一个数据结构的启发式合并。大体思路如下:
轻重链路径剖分之后,对每个点先递归处理他的所有轻儿子,每次处理完轻儿子之后把这棵子树的信息清空。最后再来处理重孩子,重儿子的信息就可以不用清空了。由于我们是用一个全局数组来记录信息的,重儿子子树的信息就仍然保留在全局数组中。接着我们另外写一个函数\(dfs\)所有的轻儿子子树,并统计答案。每统计完一棵子树的答案就可以把这棵子树的信息计入全局数组中,用于下一次更新。由于每个点到根的轻边条数是\(\log n\)级别的,所以每个点最多被扫\(\log n\)遍。
回到这道题上来。由于要求路径上的所有字符重新排列之后可以形成一个回文串,也就是说出现次数为奇数的字符不会超过\(1\)个。那么我们就可以给每个字符一个\(2^x\)形式的权值,这样的话合法路径的异或和要么为\(0\),要么为\(2^x\)的形式。
设点\(x\)到根的异或和为\(D_x\),由于这道题是边权,\(x\)和\(y\)路径上的异或和就可以用\(D_x\ xor\ D_y\)来表示。这样的话就可以用一个数组\(c\)来统计答案,其中\(c_i\)表示满足\(D_x=i\)的\(x\)的最大深度。剩下的就是套\(dsu\ on\ tree\)的板子了。
下面贴代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 500010
#define INF (1<<30) using namespace std;
typedef long long llg; int n,ci[1<<22],son[maxn],siz[maxn],dep[maxn];
int hd[maxn],nt[maxn],D[maxn],ans[maxn]; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} void dfs(int u){
siz[u]=1;
for(int i=hd[u];i;i=nt[i]){
D[i]^=D[u]; dep[i]=dep[u]+1;
dfs(i); siz[u]+=siz[i];
if(siz[i]>siz[son[u]]) son[u]=i;
}
} void undo(int u){
ci[D[u]]=-INF;
for(int i=hd[u];i;i=nt[i]) undo(i);
} int o;
void up(int &x,int y){if(y>x) x=y;}
void up(int u){
up(ans[o],dep[u]+ci[D[u]]);
for(int i=0;i<=21;i++) up(ans[o],dep[u]+ci[1<<i^D[u]]);
for(int i=hd[u];i;i=nt[i]) up(i);
} void ins(int u){
up(ci[D[u]],dep[u]);
for(int i=hd[u];i;i=nt[i]) ins(i);
} void work(int u){
for(int i=hd[u];i;i=nt[i])
if(i!=son[u]) work(i),undo(i);
if(son[u]) work(son[u]); o=u;
for(int i=hd[u];i;i=nt[i])
if(i!=son[u]) up(i),ins(i);
up(ci[D[u]],dep[u]);
up(ans[u],dep[u]+ci[D[u]]);
for(int i=0;i<=21;i++) up(ans[u],dep[u]+ci[1<<i^D[u]]);
ans[u]-=dep[u]<<1;
for(int i=hd[u];i;i=nt[i]) up(ans[u],ans[i]);
} int main(){
File("a");
n=getint();
for(int i=0;i<(1<<22);i++) ci[i]=-INF;
for(int i=2,x;i<=n;i++){
x=getint();
nt[i]=hd[x];hd[x]=i;
char c=getchar();
while(c>'v' || c<'a') c=getchar();
D[i]=1<<(c-'a');
}
dfs(1); work(1);
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
return 0;
}
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(启发式合并)
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(dsu on tree)
感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...
- Codeforces.741D.Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree 思路)
题目链接 \(Description\) 给定一棵树,每条边上有一个字符(a~v).对每个节点,求它的子树中一条最长的路径,满足 路径上所有边上的字符可以重新排列成一个回文串.输出其最长长度. \(n ...
- CF 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths [dsu on tree 类似点分治]
D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths CF741D 题意: 一棵有根树,边上有字母a~v,求每个子树中最长的边,满 ...
- 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 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位 ...
- CF 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 http://codeforces.com/problemset/probl ...
- codeforces 1065F Up and Down the Tree
题目链接:codeforces 1065F Up and Down the Tree 题意:给出一棵树的节点数\(n\)以及一次移动的最大距离\(k\),现在有一个标记在根节点1处,每一次可以进行一下 ...
- CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 好像这个题只能Dsu On Tree? 有根树点分治 统计子树过x的 ...
- Codeforces 914H Ember and Storm's Tree Game 【DP】*
Codeforces 914H Ember and Storm's Tree Game 题目链接 ORZ佬 果然出了一套自闭题 这题让你算出第一个人有必胜策略的方案数 然后我们就发现必胜的条件就是树上 ...
随机推荐
- Matlab基础部分2-数组和矩阵分析
矩阵块操作: 矩阵尺寸改变: 矩阵的查找: 矩阵的排序: 矩阵求和: 矩阵的求积: 矩阵的差分: 全零矩阵: 单位矩阵: 随机矩阵: 伴随矩阵: 方针行列式计算: 特征值: 对角矩阵: 三角矩阵: 矩 ...
- [转载]tnsnames.ora监听配置文件详解
监听配置文件 为了使得外部进程 如 CAMS后台程序 能够访问 Oracle 数据库 必须配 置 Oracle 网络服务器环境 配置 Oracle 网络 ...
- 初学delphi
今天女朋友的一门课,要求用delphi 软件编程,内容是一个计算器.当然,这个工作肯定是落在我的头上了. 这个软件是我第一次使用,边自学边进行代码编写,在n多次修改完善之后,终于成形.功能不是很多,跟 ...
- curl命令基本使用小总结
curl 下载文件 -o:将文件保存为命令行中指定的文件名的文件中 -O:使用URL中默认的文件名保存文件到本地 --limit-rate:限速 -C:对大文件使用断点续传功能 --silent:不显 ...
- 深入浅出TCP之半关闭与CLOSE_WAIT
转自:https://www.2cto.com/net/201309/243585.html(相关链接) 深入浅出TCP之半关闭与CLOSE_WAIT 终止一个连接要经过4次握手.这由TCP的半关闭( ...
- Kali系列之aircrack-ng wifi密码穷举
kali linux安全渗透 网卡:rtl8187 工具aircrack-ng 操作+ 查看无线网卡信息 ifconfig 或者 iwconfig 有个是wlan0的就是您的外置无线网卡 启动网卡监听 ...
- 18种CSS3loading效果完整版
今天把之前分享的两篇博客<CSS3实现10种Loading效果>和 <CSS3实现8种Loading效果[二]>整理了一下.因为之前所分享的各种loading效果都只是做了we ...
- OpenJudge cdqz/Data Structure Challenge 2 (Problem 5822) - 可持久化线段树
描述 给一个空数列,有M次操作,每次操作是以下三种之一: (1)在数列后加一个数 (2)求数列中某位置的值 (3)撤销掉最后进行的若干次操作(1和3) 输入 第一行一个正整数M. 接下来M行,每行开头 ...
- topcoder srm 711 div1 -3
1.给出$n,k$,求一个大于等于$n$且最小的数字$m$使得$m$的二进制表示中存在连续$k$个1 . 思路:如果$n$满足,答案就是$n$.否则,依次枚举连续1的位置判断即可. #include ...
- Linux电源管理_autosleep--(五)【转】
本文转载自:https://blog.csdn.net/wlsfling/article/details/46005409 1. 前言 Autosleep也是从Android wakelocks补丁集 ...