博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CF 741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
阅读量:5287 次
发布时间:2019-06-14

本文共 2638 字,大约阅读时间需要 8 分钟。

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

题意:

  一棵根为1 的树,每条边上有一个字符(a-v共22种)。 求每个子树内的最长的路径,使得路径上的边按照一定顺序排列后是回文串。

分析:

  dsu on tree。询问子树信息。

  首先将这22个字符,转化为二进制。a=1,b=10,c=100...如果一条路径可以是回文串,那么要求路径的异或和最多有一个1。所以记录下从根到每个点的异或和,那么一条路径的异或和就是dis[u]^dis[v],lca上面的异或后消失了。

  之后维护每个子树内异或和为x的最大深度是多少。记为f。

  更新答案:按照点分治的思想,先更新不经过根的,然后求出经过根的(更新分成两步,第一步更新答案,第二步更新f数组。防止更新了在子树内部的)。

代码:

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 using namespace std;12 typedef long long LL;13 14 inline int read() {15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;17 }18 19 const int N = 500005;20 21 int head[N], nxt[N], to[N], len[N], En;22 int fa[N], siz[N], son[N], dis[N], deth[N], ans[N];23 int f[(1 << 22) + 5];24 int Mx, D;25 26 void add_edge(int u,int v,int w) {27 ++En; to[En] = v; len[En] = w; nxt[En] = head[u]; head[u] = En;28 }29 30 void dfs(int u) {31 siz[u] = 1;32 deth[u] = deth[fa[u]] + 1;33 for (int i=head[u]; i; i=nxt[i]) {34 int v = to[i];35 fa[v] = u;36 dis[v] = dis[u] ^ (1 << len[i]);37 dfs(v);38 siz[u] += siz[v];39 if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;40 }41 }42 43 void add(int u) {44 if (f[dis[u]]) Mx = max(Mx, deth[u] + f[dis[u]] - D); // 异或后为0 45 for (int i=0; i<22; ++i) // 异或后有一个1 46 if (f[(1 << i) ^ dis[u]]) Mx = max(Mx, deth[u] + f[(1 << i) ^ dis[u]] - D);47 }48 void Calc(int u) { // 计算答案 49 add(u);50 for (int i=head[u]; i; i=nxt[i]) Calc(to[i]);51 }52 void upd(int u) {53 f[dis[u]] = max(deth[u], f[dis[u]]);54 }55 void update(int u) { // 更新f数组 56 upd(u);57 for (int i=head[u]; i; i=nxt[i]) update(to[i]);58 }59 void Clear(int u) {60 f[dis[u]] = 0;61 for (int i=head[u]; i; i=nxt[i]) Clear(to[i]);62 }63 64 void solve(int u,bool c) {65 for (int i=head[u]; i; i=nxt[i]) 66 if (to[i] != son[u]) solve(to[i], 0);67 if (son[u]) solve(son[u], 1);68 69 D = deth[u] * 2;70 for (int i=head[u]; i; i=nxt[i]) Mx = max(Mx, ans[to[i]]); //不经过根的 71 for (int i=head[u]; i; i=nxt[i]) 72 if (to[i] != son[u]) Calc(to[i]), update(to[i]); // update(u) !!! 先更新答案,在更新f数组,(防止计算到在子树内部的路径) 73 add(u); upd(u);74 ans[u] = Mx;75 if (!c) Clear(u), Mx = 0;76 }77 78 int main() {79 int n = read();80 char c[10];81 for (int i=2; i<=n; ++i) {82 int u = read(); scanf("%s", c); 83 add_edge(u, i, c[0] - 'a');84 }85 dfs(1);86 solve(1, 1);87 for (int i=1; i<=n; ++i) printf("%d ",ans[i]);88 return 0;89 }

 

转载于:https://www.cnblogs.com/mjtcn/p/9711703.html

你可能感兴趣的文章
UITableView
查看>>
sql语句学习
查看>>
给大家推荐常用的正则表达式
查看>>
【SAS ADVANCE】Performing Advanced Queries Using PROC SQL
查看>>
20165337第四周课上补做
查看>>
hexo基本操作
查看>>
mvc BundleConfig实现对Css、Js压缩打包加载
查看>>
day11
查看>>
8位、24位、32位图像数据转换
查看>>
XSBASE 270-S_裸机程序_流水灯
查看>>
手机扫描文字如何用软件识别
查看>>
收藏一些常用的methods
查看>>
强制不按行
查看>>
h5视频播放插件
查看>>
jQuery 与 Ajax 的应用
查看>>
第2次作业:软件案例分析
查看>>
05-Hibernate的核心API及使用c3p0连接池
查看>>
39. Combination Sum
查看>>
Web 研发模式演变
查看>>
RS485通讯协议的应用 (转)
查看>>