codeforces 570D.Tree Requests
[题目大意]:
给定一棵树,树的每个节点对应一个小写字母字符,有m个询问,每次询问以vi为根节点的子树中,深度为hi的所有节点对应的字符能否组成一个回文串;
[题目分析]:
先画个图,可看出每次询问的所有节点都是一个从1开始bfs遍历完成的节点序列中的一段,已知深度hi的情况下,可以二分得到深度为hi的那一段的位置;
那么如何满足找到的节点必须在以vi为根的子树内这个条件?
可以想到dfs的时间戳,把1-n的数组按深度排序,深度相同的按照dfs时间戳排序;
这样就可以二分得到要求的所有节点的位置;
这样可以O(n)
分析回文串可知,如果奇数数量的字符不超过1个,那么一定能组成回文串;
用前缀和xor优化;
可以做到O(nlogn);
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
#include<map>
#include<set>
#include<vector>
#include<ctime>
#include<cmath>
using namespace std;
#define LL long long
#define up(i,j,n) for(int i=(j);(i)<=(n);(i)++)
#define max(x,y) ((x)<(y)?(y):(x))
#define min(x,y) ((x)<(y)?(x):(y))
#define FILE "1"
#define pii pair<int,int>
const int maxn=,inf=;
int read(){
int x=;bool flag=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')flag=;ch=getchar();}
while(ch<=''&&ch>=''){x=x*+ch-'';ch=getchar();}
return flag?-x:x;
}
struct node{
int y,next;
}e[maxn<<];
int n,m;
int linkk[maxn],len=,sum[maxn];
int dfs_clock=,fa[maxn];
char s[maxn];
int f[maxn];
struct Node{
int dep,pre,lat,id;
bool operator<(const Node &b)const{return dep<b.dep||(dep==b.dep&&pre<b.pre);}
}a[maxn];
void insert(int x,int y){
e[++len].y=y;
e[len].next=linkk[x];
linkk[x]=len;
}
void dfs(int x){
a[x].pre=++dfs_clock;a[x].id=x;
for(int i=linkk[x];i;i=e[i].next){
if(e[i].y==fa[x])continue;
a[e[i].y].dep=a[x].dep+;
dfs(e[i].y);
}
a[x].lat=++dfs_clock;
}
void init(){
n=read(),m=read();int x;
up(i,,n){
x=read();
insert(i,x);
insert(x,i);
fa[i]=x;
}
scanf("%s",s+);
a[].dep=;
dfs();
sort(a+,a+n+);
for(int i=;i<=n;i++)f[a[i].id]=i;
}
int find(int x,int Dep){
int left=,right=n,mid;
int L=,R=;
while(left<=right){
mid=(left+right)>>;
if(a[mid].dep<Dep)left=mid+;
else {
right=mid-;
if(a[mid].dep==Dep)L=mid;
}
}
left=,right=n,mid=;
while(left<=right){
mid=(left+right)>>;
if(a[mid].dep<=Dep){
left=mid+;
if(a[mid].dep==Dep)R=mid;
}
else right=mid-;
}
if(!L&&!R)return ;
left=L,right=R;
int u=,v=;
while(left<=right){
mid=(left+right)>>;
if(a[mid].pre>=a[f[x]].pre){
right=mid-;
if(a[mid].pre>=a[f[x]].pre&&a[mid].pre<=a[f[x]].lat)u=mid;
}
else left=mid+;
}
left=L,right=R;
while(left<=right){
mid=(left+right)>>;
if(a[mid].pre<=a[f[x]].lat){
left=mid+;
if(a[mid].pre>=a[f[x]].pre&&a[mid].pre<=a[f[x]].lat)v=mid;
}
else right=mid-;
}
if(!u||!v)return ;
int p=sum[v]^sum[u-];
int cnt=;
while(p){
if(p&)cnt++;
p>>=;
}
if(cnt>=)return ;
else return ;
}
void work(){
int x,y;
for(int i=;i<=n;i++)sum[i]=sum[i-]^(<<(s[a[i].id]-'a'));
while(m--){
x=read(),y=read();
if(find(x,y))printf("Yes\n");
else printf("No\n");
}
}
int main(){
init();
work();
return ;
}
codeforces 570D.Tree Requests的更多相关文章
- Codeforces 570D - Tree Requests(树上启发式合并)
570D - Tree Requests 题意 给出一棵树,每个节点上有字母,查询 u k,问以 u 为根节点的子树下,深度为 k 的所有子节点上的字母经过任意排列是否能构成回文串. 分析 一个数组 ...
- Codeforces 570D TREE REQUESTS dfs序+树状数组 异或
http://codeforces.com/problemset/problem/570/D Tree Requests time limit per test 2 seconds memory li ...
- Codeforces 570D TREE REQUESTS dfs序+树状数组
链接 题解链接:点击打开链接 题意: 给定n个点的树.m个询问 以下n-1个数给出每一个点的父节点,1是root 每一个点有一个字母 以下n个小写字母给出每一个点的字母. 以下m行给出询问: 询问形如 ...
- Codeforces 570D - Tree Requests【树形转线性,前缀和】
http://codeforces.com/contest/570/problem/D 给一棵有根树(50w个点)(指定根是1号节点),每个点上有一个小写字母,然后有最多50w个询问,每个询问给出x和 ...
- CodeForces 570D - Tree Requests - [DFS序+二分]
题目链接:https://codeforces.com/problemset/problem/570/D 题解: 这种题,基本上容易想到DFS序. 然后,我们如果再把所有节点分层存下来,那么显然可以根 ...
- CF 570D. Tree Requests [dsu on tree]
传送门 题意: 一棵树,询问某棵子树指定深度的点能否构成回文 当然不用dsu on tree也可以做 dsu on tree的话,维护当前每一个深度每种字母出现次数和字母数,我直接用了二进制.... ...
- codeforces 570 D. Tree Requests 树状数组+dfs搜索序
链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds mem ...
- Codeforces Round #316 (Div. 2) D. Tree Requests dfs序
D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- codeforces 570 D. Tree Requests (dfs)
题目链接: 570 D. Tree Requests 题目描述: 给出一棵树,有n个节点,1号节点为根节点深度为1.每个节点都有一个字母代替,问以结点x为根的子树中高度为h的后代是否能够经过从新排序变 ...
随机推荐
- vue 权限控制按钮3种样式、内容、以及跳转事件
最近碰到一个因为要根据权限来给一个按钮变成不同功能, 简单写出3个按钮然后用v-if也能实现这个功能,但是在加载页面时,如果延迟过高则会把按钮按照DOM顺序加载出来,这是个很不好的效果 思索了下,把三 ...
- 移动端自动化测试(一)appium环境搭建
自动化测试有主要有两个分类,接口自动化和ui自动化,ui自动化呢又分移动端的和web端的,当然还有c/s架构的,这种桌面程序应用的自动化,使用QTP,只不过现在没人做了. web自动化呢,现在基本上都 ...
- Java 基础【04】数组内存分配
可能Java 数组大家都很熟悉,最近我遇到了一个关于Java 数组内存分配的问题. 突然发现许多书上“基本数据类型存储在栈内存当中,对象则保存在堆内存”这句话完全是错误的.下面是个简单的例子代码: p ...
- 新华三孟丹:NFV资源池实现中的技术探讨
近日,在第三届未来网络发展大会SDN/NFV技术与应用创新分论坛上,新华三解决方案部架构师孟丹女士发表了主题为<NFV资源池实现中的技术探讨>的主题演讲. 孟丹指出,新华三的NFV核心理念 ...
- Java中String/StringBuffer/StringBuilder区别(转)
1.三者在执行速度方面的比较:StringBuilder > StringBuffer > String 2.String <(StringBuffer,StringBuild ...
- 深入理解Activity启动流程(一)–Activity启动的概要流程
概述 Android中启动某个Activity,将先启动Activity所在的应用.应用启动时会启动一个以应用包名为进程名的进程,该进程有一个主线程,叫ActivityThread,也叫做UI线程. ...
- ubuntu 配置 django
安装 安装Apache sudo apt-get install apache2 安装Django 下载Django 安装mod_wsgi sudo apt-get install libapache ...
- 算法之美--3.2.3 KMP算法
不知道看了几遍的kmp,反正到现在都没有弄清楚next[j]的计算和kmp的代码实现,温故而知新,经常回来看看,相信慢慢的就回了 从头到尾彻底理解KMP 理解KMP /*! * \file KMP_算 ...
- Maven引入本地Jar包并打包进War包中
1.概述 在平时的开发中,有一些Jar包因为种种原因,在Maven的中央仓库中没有收录,所以就要使用本地引入的方式加入进来. 2. 拷贝至项目根目录 项目根目录即pom.xml文件所在的同级目录,可以 ...
- log4net菜鸟指南二----生成access和txt
前言 有可能目标计算机缺少某些组件,导致无法生成access文件,或者打不开文件,这时txt文件就可以方便的使用了 一,标准的控制台程序输出日志到access <?xml version=&qu ...