#树上启发式合并,位运算#CF570D Tree Requests
题目
给定一个以 \(1\) 为根的 \(n\) 个结点的树,每个点上有一个字母\((a-z)\),每个点的深度定义为该节点到 \(1\) 号结点路径上的点数。
每次询问 \(a, b\) 查询以 \(a\) 为根的子树内深度为 \(b\) 的结点上的字母重新排列之后是否能构成回文串。
分析
回文串最多出现一个奇数次字母,考虑26个字母用位运算的异或,
设\(dp[dep]\)表示以\(1\)号点为根深度为\(dep\)的异或值,
那么这个用树上启发式合并就可以做到\(O(nlogn)\)
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <vector>
#define rr register
using namespace std;
const int N=500011;
struct rec{int depth,rk;}; vector<rec>Q[N];
struct node{int y,next;}e[N]; char s[N];
int dep[N],fat[N],root,n,siz[N],Qt,big[N],as[N],dp[N],ans[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,fat[x]=fa,siz[x]=1;
for (rr int i=as[x],SIZ=-1;i;i=e[i].next){
dfs1(e[i].y,x),siz[x]+=siz[e[i].y];
if (siz[e[i].y]>SIZ) big[x]=e[i].y,SIZ=siz[e[i].y];
}
}
inline bool check(int d){return dp[d]==(-dp[d]&dp[d]);}
inline void update(int x){
dp[dep[x]]^=1<<(s[x]-97);
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=root)
update(e[i].y);
}
inline void dfs2(int x,int opt){
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=big[x]) dfs2(e[i].y,0);
if (big[x]) dfs2(big[x],1),root=big[x];
rr int len=Q[x].size(); update(x);
for (rr int i=0;i<len;++i)
ans[Q[x][i].rk]=check(Q[x][i].depth);
if (!opt) root=0,update(x);
}
signed main(){
n=iut(),Qt=iut();
for (rr int i=2;i<=n;++i){
rr int x=iut();
e[i]=(node){i,as[x]},as[x]=i;
}
scanf("%s",s+1),dfs1(1,0);
for (rr int i=1;i<=Qt;++i){
rr int x=iut(),h=iut();
Q[x].push_back((rec){h,i});
}
dfs2(1,0);
for (rr int i=1;i<=Qt;++i)
puts(ans[i]?"Yes":"No");
return 0;
}
#树上启发式合并,位运算#CF570D Tree Requests的更多相关文章
- 【Luogu U41492】树上数颜色——树上启发式合并(dsu on tree)
(这题在洛谷主站居然搜不到--还是在百度上偶然看到的) 题目描述 给一棵根为1的树,每次询问子树颜色种类数 输入输出格式 输入格式: 第一行一个整数n,表示树的结点数 接下来n-1行,每行一条边 接下 ...
- 算法学习笔记(19): 树上启发式合并(DSU on tree)
树上启发式合并 DSU on tree,我也不知道DSU是啥意思 这是一种看似特别玄学的优化 可以把树上部分问题由 \(O(n^2)\) 优化到 \(O(n \log n)\). 例如 CodeFor ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
- CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 树上启发式合并(DSU ON TREE)
题目描述 一棵根为\(1\) 的树,每条边上有一个字符(\(a-v\)共\(22\)种). 一条简单路径被称为\(Dokhtar-kosh\)当且仅当路径上的字符经过重新排序后可以变成一个回文串. 求 ...
- 树上启发式合并(dsu on tree)
树上启发式合并属于暴力的优化,复杂度O(nlogn) 主要解决的问题特点在于: 1.对于树上的某些信息进行查询 2.一般问题的解决不包含对树的修改,所有答案可以离线解决 算法思路:这类问题的特点在于父 ...
- 树上启发式合并(DSU on tree)
//heavy-light decomposition style .//http://codeforces.com/blog/entry/44351 int cnt[maxn]; bool big[ ...
- hdu6191(树上启发式合并)
hdu6191 题意 给你一棵带点权的树,每次查询 \(u\) 和 \(x\) ,求以 \(u\) 为根结点的子树上的结点与 \(x\) 异或后最大的结果. 分析 看到子树,直接上树上启发式合并,看到 ...
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- 神奇的树上启发式合并 (dsu on tree)
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...
- dsu on tree (树上启发式合并) 详解
一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...
随机推荐
- django的orm多表查询作业第五题答案
5.每个作者出版的所有书的最高价格以及最高价格的那本书的名称. 用django的模型类写不出来的,只能用原生sql写这题 关于第五题,mysql5.7及以上版本,使用下面的答案 set sql_mod ...
- Mysql基础目录
尚硅谷Mysql课程笔记 课程链接: https://www.bilibili.com/video/BV1iq4y1u7vj?p=1 第01章_数据库概述 第02章_MySQL环境搭建 第03章_基本 ...
- Java 封装性的四种权限测试 + 总结
* 总结封装性:Java提供了4中权限修饰符来修饰类及类的内部结构,体现类及类的内部结构再被调用时的可见性的大小 1 package com.bytezero.circle; 2 3 publi ...
- [学习笔记] Rocket.Chat 安装与设置启动项
这篇文章主要介绍手动安装的方式来安装Rocket.Chat,在Rocket.Chat官方有三种安装方式, 面向开发人员的直接使用meteor部署 传统的源码编译安装 Docker方式部署 接下来分别介 ...
- inner join on 1=1 在查询中的高级用法
最近在项目中看到一个查询语句,让我有兴趣去研究.研究.查询语句如下: 重点分析第二个INNER JOIN ON 1 = 1 这个语句:内连接表示查询两个表的交集,而且ON的条件为 1=1 就表示连接 ...
- 别名路径跳转 - vscode 插件
别名路径跳转 - vscode 插件
- 基于python中librosa的声音混音实例解析
一 概念 1.一些概念 Librosa是一个用于音频.音乐分析.处理的python工具包,一些常见的时频处理.特征提取.绘制声音图形等功能应有尽有,功能十分强大.本文主要介绍libros的基本用法 ...
- pyecharts + Django你不知道这个架构有多美
pyecharts + Django你不知道这个架构有多美 何为echarts? pyecharts 是一个用于生成 Echarts 图表的类库.Echarts 是百度开源的一个数据可视化 JS ...
- C++一些新的特性的理解
一.智能指针 为什么需要智能指针? 智能指针主要解决一下问题: 内存泄漏:内存手动释放,使用智能指针可以自动释放 共享所有权的指针的传播和释放,比如多线程使用同一个对象时析构的问题. C++里面的四个 ...
- day01-项目介绍和功能实现
项目练习01 1.项目介绍 这是一个简单的项目练习,用于掌握新学习的SpringBoot技术. 项目操作界面 ● 技术栈 Vue3+ElementPlus+Axios+MyBatisPlus+Spri ...