【题解】Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths Codeforces 741D DSU on Tree
Prelude
很好的模板题。
传送到Codeforces:(* ̄3 ̄)╭
Solution
首先要会DSU on Tree,不会的看这里:(❤ ω ❤)。
众所周知DSU on Tree是可以用来处理子树信息的,但是有时候也可以用来处理链上信息。
IOI 2011 Race是一道著名的点分治模板题,要求统计链信息,也可以用DSU on Tree来做,题目链接在这里:(✿◕‿◕✿)。
基本思路和点分治是一样的,对于每个点u,我们统计出所有经过u的路径的信息。
于是我们有了一个非常好的思路:统计每个点u的时候,我们记录下u的所有子孙节点到u的信息,放在某个数组里面。
以这道题为例子,我们把每个字符串压缩为一个二进制串,然后就可以记录u的每个后继节点到u的路径所形成的字符串。
但是问题来了,我们要保留重儿子的信息,但是节点u和她的重儿子之间有一个字母,我们要把这个字母加到重儿子的所有后继节点上,这不是就退化成了暴力了么?
对于IOI 2011 Race这样的题,我们可以选择用数据结构维护,于是复杂度多了一个log。
当然还有更简单的做法,对于本题和IOI 2011 Race这样的题,链上的信息是可减的,于是我们可以不保存“后继节点到点u”的信息,而是保存“后继节点到根”的信息,然后在统计的时候再减去“u到根的信息”。
每个节点到根的信息是不会变的,就不需要维护了,又因为路径信息可减,所以处理起来也很方便。
当然,对于不可减的路径信息,可以选择用数据结构维护。
当然,如果维护不了的话还是写好写好调的点分治吧qwq。
Code
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 500010;
const int INF = 0x3f3f3f3f;
int _w;
int n, ans[MAXN];
namespace G {
int head[MAXN], nxt[MAXN], to[MAXN], val[MAXN], eid;
void init() {
memset(head, -1, sizeof head);
}
void adde( int u, int v, int w ) {
to[eid] = v, val[eid] = w;
nxt[eid] = head[u], head[u] = eid++;
}
}
int sz[MAXN], dep[MAXN], pa[MAXN], son[MAXN], str[MAXN];
int prelude( int u, int fa, int d, int s ) {
using namespace G;
sz[u] = 1, dep[u] = d, pa[u] = fa, str[u] = s;
for( int i = head[u]; ~i; i = nxt[i] ) {
int v = to[i], t = 1<<val[i];
sz[u] += prelude(v, u, d+1, s^t);
if( sz[v] > sz[son[u]] )
son[u] = v;
}
return sz[u];
}
int maxd[1<<22];
void ans_node( int s, int d, int &ans ) {
ans = max(ans, d + maxd[s]);
for( int i = 0; i < 22; ++i )
ans = max(ans, d + maxd[s^(1<<i)]);
}
void dfs_ans( int u, int &ans ) {
using namespace G;
ans_node(str[u], dep[u], ans);
for( int i = head[u]; ~i; i = nxt[i] )
dfs_ans(to[i], ans);
}
void ins_node( int s, int d ) {
maxd[s] = max(maxd[s], d);
}
void dfs_ins( int u ) {
using namespace G;
ins_node(str[u], dep[u]);
for( int i = head[u]; ~i; i = nxt[i] )
dfs_ins(to[i]);
}
void del_node( int s ) {
maxd[s] = -INF;
}
void dfs_del( int u ) {
using namespace G;
del_node(str[u]);
for( int i = head[u]; ~i; i = nxt[i] )
dfs_del(to[i]);
}
void solve( int u, bool clr ) {
using namespace G;
for( int i = head[u]; ~i; i = nxt[i] )
if( to[i] != son[u] )
solve(to[i], 1);
if( son[u] ) solve(son[u], 0);
ans_node(str[u], dep[u], ans[u]);
ins_node(str[u], dep[u]);
for( int i = head[u]; ~i; i = nxt[i] )
if( to[i] != son[u] ) {
dfs_ans(to[i], ans[u]);
dfs_ins(to[i]);
}
if( clr ) dfs_del(u);
ans[u] -= dep[u] + dep[u];
for( int i = head[u]; ~i; i = nxt[i] )
ans[u] = max(ans[u], ans[to[i]]);
ans[u] = max(ans[u], 0);
}
int main() {
_w = scanf( "%d", &n );
G::init();
for( int i = 2; i <= n; ++i ) {
int pa;
char ch;
_w = scanf( "%d %c", &pa, &ch );
G::adde(pa, i, ch - 'a');
}
for( int i = 0; i < (1<<22); ++i )
maxd[i] = -INF;
prelude(1, 0, 1, 0), solve(1, 0);
for( int i = 1; i <= n; ++i )
printf( "%d ", ans[i] );
puts("");
return 0;
}
【题解】Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths Codeforces 741D DSU on Tree的更多相关文章
- dsu on tree学习笔记
前言 一次模拟赛的\(T3\):传送门 只会\(O(n^2)\)的我就\(gg\)了,并且对于题解提供的\(\text{dsu on tree}\)的做法一脸懵逼. 看网上的其他大佬写的笔记,我自己画 ...
- 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 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...
- 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 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位 ...
- 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 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\ o ...
- 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】741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
[题意]给定n个点的树,每条边有一个小写字母a~v,求每棵子树内的最长回文路径,回文路径定义为路径上所有字母存在一种排列为回文串.n<=5*10^5. [算法]dsu on tree [题解]这 ...
- CF741 D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
题目意思很清楚了吧,那么我们从重排回文串的性质入手. 很容易得出,只要所有字符出现的次数都为偶数,或者有且只有一个字符出现为奇数就满足要求了. 然后想到什么,Hash?大可不必,可以发现字符\(\in ...
随机推荐
- node上的__dirname和./的区别
概要 Node.js 中,__dirname 总是指向被执行 js 文件的绝对路径,所以当你在 /d1/d2/myscript.js 文件中写了 __dirname, 它的值就是 /d1/d2 . 相 ...
- java中重要的多线程工具类
前言 之前学多线程的时候没有学习线程的同步工具类(辅助类).ps:当时觉得暂时用不上,认为是挺高深的知识点就没去管了.. 在前几天,朋友发了一篇比较好的Semaphore文章过来,然后在浏览博客的时候 ...
- [java] jar file
查看 .jar 内的文件 jar tf jarfile.jar maven 项目中, java 读取目标文件 运行 mvn package 打包项目是, src/main/resources 下的文件 ...
- iOS开发日常遇到问题记录
1. [self.navigationController.navigationBar setTranslucent:NO]; iOS 7 之后,setTranslucent=yes 默认的 则状 ...
- Cocoapods更改安装版本及卸载、ruby版本检测和安装
修改于:2017.1.10 我们实际过程中会遇到很多的问题,并且各式各样,特别是各种系统.工具版本升级后遇到的问题,最后的杀手锏就是彻底删干净,重装. 一. 移除pod组件 这条指令会告诉你Cocoa ...
- Daily Scrumming 2015.10.23(Day 4)
今明两天任务表 Member Today’s Task Tomorrow’s Task 江昊 继续学习rails ActiveRecord 数据库迁移 域名备案申请 学习rails router配置与 ...
- 【CS231N】4、神经网络
一.疑问 二.常用激活函数 1. Sigmoid sigmoid将输入实数值"挤压"到0到1范围内.更具体地说,很大的负数变成0,很大的正数变成1.它对于神经元的激活频率有良好 ...
- 团队作业7——第二次项目冲刺(Beta版本12.07——12.08)
1.当天站立式会议照片 本次会议在5号公寓3楼召开,本次会议内容:①:熟悉每个人想做的模块.②:根据项目要求还没做的完成. 2.每个人的工作 经过会议讨论后确定了每个人的分工 组员 任务 陈福鹏 实现 ...
- 第五次作业——python效能分析与几个问题(个人作业)
第五次作业--效能分析与几个问题(个人作业) 前言 阅读了大家对于本课程的目标和规划之后,想必很多同学都跃跃欲试,迫不及待想要提高自身实践能力,那么就从第一个个人项目开始吧,题目要求见下. 阅读 阅读 ...
- 浅学JavaScript
JavaScript是互联网上最流行的脚本语言,可广泛用于服务器.PC.笔记本电脑智能手机等设备: 对事件的反应: <!DOCTYPE html> <html> <hea ...